google / google/adk-python

RestApiTool path parameters with '.' / '..' still reach the wire after quote(safe="")

オープン
#7,065 コメント 4 件 リアクション 0 件 担当者 1 名 @sanketpatil06 が担当を希望しています GitHub で見る
tools
主要言語
Python
スター
21.5k
フォーク
4k
平均マージ
1日 14時間
マージ済み PR(30日)
37

説明

## 🔴 Required Information

**Describe the Bug:**
`RestApiTool` (`google.adk.tools.openapi_tool`) percent-encodes path parameter values with `urllib.parse.quote(value, safe="")` and documents that this prevents a model-supplied value from redirecting the request onto an undeclared path on the same host.

That guarantee does not hold for RFC 3986 dot-segments. `quote()` never encodes `.` (it is unreserved), so a value containing `..` is sent with literal dot-dot segments joined by encoded slashes. Backends/gateways that decode `%2F` and then merge dot-segments can dispatch the request — with the tool's configured credentials — to a path the OpenAPI spec never declared.

```python
>>> from urllib.parse import quote
>>> quote("../../admin/secret", safe="")
'..%2F..%2Fadmin%2Fsecret'
```

This is a hardening follow-up to the merged encoding fix (`25f53bd`). Google VRP issue 557701521 was closed as Infeasible (not tracked as a security bug) with a request to file this publicly.

**Steps to Reproduce:**
1. Use an OpenAPI spec that declares only `GET /files/{name}` against a host that also serves an undeclared route such as `GET /admin/secret`.
2. Call the generated tool with `args={"name": "../../admin/secret"}`.
3. Observe the outgoing request line `GET /files/..%2F..%2Fadmin%2Fsecret`.
4. On a backend that decodes `%2F` then merges dot-segments (e.g. a Go router over `path.Clean(r.URL.Path)`, nginx as a gateway), the undeclared `/admin/secret` body is returned as the tool result.

**Expected Behavior:**
Path parameters whose `/`- or `\`-separated segments are `.` or `..` are rejected before any HTTP request is sent. `quote(safe="")` continues to encode `/`, `?`, and `#`. Slash-containing IDs such as `foo/bar` remain encoded as `foo%2Fbar`.

**Observed Behavior:**
The client emits `GET /files/..%2F..%2Fadmin%2Fsecret`. httpx correctly treats `%2F` as data, so the dot-dot sequences reach the backend unchanged.

**Environment Details:**

- ADK Library Version (pip show google-adk): 2.8.0 (`a119dd7751082dbbd9a65f71e359abdc2be659cc`)
- Desktop OS: macOS
- Python Version (python -V): 3.12 / 3.13

**Model Information:**

- Are you using LiteLLM: N/A (library-level RestApiTool)
- Which model is being used: N/A

---

## 🟡 Optional Information

**Regression:**
Present in any release that contains the `quote(safe="")` path-param encoding fix.

**Minimal Reproduction Code:**
```python
from urllib.parse import quote
print(quote("../../admin/secret", safe="")) # '..%2F..%2Fadmin%2Fsecret'
```

**Additional Context:**

Backend behavior for `GET /files/..%2F..%2Fadmin%2Fsecret`:

- Hand-rolled Go routers that clean the decoded path (`path.Clean(r.URL.Path)`): request is dispatched to `/admin/secret`.
- Legacy Go ServeMux (pre-1.22 / `GODEBUG=httpmuxgo121=1`): 301 to `/admin/secret`. ADK does not follow redirects; a following intermediary would complete the access.
- Modern Go ServeMux (>= 1.22), FastAPI/Starlette direct, Envoy defaults: not affected (`%2F` stays one segment).
- nginx as gateway: decode-and-merge by documented analysis.

Same host/port only (origin is fixed by the spec). Suggested client-side fix: reject `.` / `..` as path segments, then keep `quote(safe="")`.

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。