Conversation
Contributor
There was a problem hiding this comment.
5 issues found across 16 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
…gins Follow-up to the GHSA-9qhg-99ww-9mqc / GHSA-8cp3-qxj6-px34 / GHSA-ppx3-28rw-8fpf fixes shipped in 1.1.4 / 1.1.1 / 1.1.1. A post-fix audit surfaced six bugs ranging from real exploits to availability papercuts; this commit lands all of them. Loopback detection now covers wildcard binds and the IPv4-mapped IPv6 forms that bypass Python's stdlib `is_loopback`. * `is_loopback_url` returns True for `0.0.0.0`, `::`, the entire `127.0.0.0/8` range, and `::ffff:127.x.x.x` (IPv4-mapped IPv6 loopback). On Linux a connect to any of these lands on local loopback; the OpenAPI converter's "remote spec declares a loopback server" SSRF defense now actually catches them. Cross-origin redirect helper now scrubs everything the OAuth / API- key threat model requires: * Auth header set extended beyond the canonical four to include `X-Api-Key`, `Api-Key`, `X-Auth-Token`, `X-Access-Token`, `X-Csrf-Token`, `X-Xsrf-Token`, `X-Amz-Security-Token`, `X-Goog-Api-Key`, plus a regex catch-all matching ad-hoc auth-looking names (`X-MyApp-Token`, `Custom-Bearer`, etc.). Without this, `ApiKeyAuth` headers under arbitrary names rode through cross-origin 302s. * Request body (`json` / `data`) is now dropped on cross-origin redirect. 307 / 308 preserve method + body per RFC 7231, which would otherwise resend an OAuth2 token POST (containing `client_secret`) to an attacker-controlled `Location`. Browsers prompt the user; we have no user, so we strip. * `proxy_auth` is now also dropped on cross-origin so a proxy's Basic credentials are not forwarded to a new origin's proxy. * Same-origin check normalises default ports so `https://x` and `https://x:443` are recognised as the same origin -- the previous comparison treated them as different origins and silently stripped `Authorization` on legitimate same-origin redirects. WebSocket protocol: * `ws_connect` no longer receives the invalid `allow_redirects` kwarg the previous fix added -- aiohttp's `ws_connect` does not accept it. The pre-flight URL validation via `ensure_secure_ws_url` already constrains the handshake; the one-shot upgrade naturally rejects 3xx. * `_substitute_placeholders` gained a `json_string_context` mode. When the `message` field of `WebSocketCallTemplate` is a string that looks like JSON (`{...}` / `[...]`), string substitutions are run through `json.dumps(...)[1:-1]` so a tool_arg containing `"` cannot break out of the surrounding string literal and inject extra JSON fields. Dict templates were already safe via the outer `json.dumps`. SSE protocol: * `ClientSession` is now closed in a `finally` block on the success path of `call_tool_streaming`. The previous version closed it only in `except`, leaking the session on every normal-completion stream. OpenAPI converter: * `tokenUrl` validation handles relative references per the OpenAPI 3.0 / 3.1 spec. Absolute URLs still go through `ensure_secure_url` eagerly; relative URLs are resolved against `spec_url` if available (and the resolved URL is validated). Without a `spec_url` the eager check defers to the runtime `_handleOAuth2` validation. Fixes the regression where `"tokenUrl": "/oauth/token"` was rejected as non-loopback / non-HTTPS. GraphQL protocol: * `_SecureAIOHTTPTransport` subclass patches `session.post` with `allow_redirects=False` from inside `connect()`, before the `GqlClient.__aenter__` schema-introspection request fires. The previous fix patched the session AFTER entering the context, leaving the very first GraphQL request unprotected. Regression tests cover: * loopback detection of `0.0.0.0`, `::`, `127.0.0.2`, `::ffff:127.0.0.1`, plus negatives; * OpenAPI converter rejecting wildcard / 127.0.0.x / IPv4-mapped server URLs from a remote spec; * cross-origin redirect stripping custom `X-Api-Key` / `X-MyApp-Token` while preserving a benign `X-Trace-Id`; * cross-origin 307 dropping the OAuth POST body so `client_secret` cannot reach the attacker; * same-origin redirect with explicit default port keeping `Authorization`; * WebSocket JSON-shaped string template escaping tool_arg `"` characters, dict template remaining safe, and non-JSON string templates substituting raw (back-compat). Version bumps: * utcp-http 1.1.4 -> 1.1.5 * utcp-gql 1.1.1 -> 1.1.2 * utcp-websocket 1.1.1 -> 1.1.2 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
6 issues found across 13 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary by cubic
Post‑audit hardening for HTTP, GraphQL, and WebSocket to block SSRF and credential leaks. Tightens URL/loopback checks, secures redirects and OAuth2 token handling (incl. relative token URLs), patches GraphQL introspection, and hardens WebSocket message templating; adds tests and bumps versions.
Bug Fixes
https:///wss://allowed;http:///ws://loopback only (covers0.0.0.0,::, full127.0.0.0/8, IPv4‑mapped IPv6).safe_request_with_redirects: strip auth‑like headers, request body, and proxy creds on cross‑origin; normalize default ports for same‑origin; used for manual discovery, tool calls, OAuth2 across HTTP/SSE/WS.token_urlat runtime and during OpenAPI conversion; resolve relativetokenUrlagainstspec_urland validate.ClientSessioncloses on success to prevent leaks.Dependencies
utcp-httpto 1.1.6,utcp-gqlto 1.1.3,utcp-websocketto 1.1.3.aiohttp>=3.8toutcp-gql.Written for commit 2cc003b. Summary will update on new commits.