google / google/adk-python

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

Đang mở
#7,065 4 bình luận 0 reaction 1 người được giao Được @sanketpatil06 nhận Xem trên GitHub
tools
Ngôn ngữ chính
Python
Star
21.5k
Fork
4k
Merge trung bình
1 ngày 14 giờ
Pull request đã merge (30 ngày)
37

Mô tả

## 🔴 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="")`.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.