Repository navigation
http/websocket: a host chosen after registration can never be loopback - #116
Merged
Merged
Conversation
utcp-http 1.1.15: at call time a resolved URL may be loopback only when the
template literally names a loopback host, so a `{host}` placeholder filled
with 127.0.0.1 is refused before any request leaves; a remote manual or
OpenAPI spec may not route the OAuth2 token POST at loopback either; server
variables resolve to their defaults; the converter judges the spec by its
final post-redirect URL.
utcp-websocket 1.2.1: the upgrade never follows a redirect, and a manual
discovered from a remote origin may not point tool calls or a token URL at
loopback.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 14 files
Tip: Get a Slack DM when cubic finishes reviewing your PRs. Connect Slack
View guided diff | Turn on auto-fix | Re-trigger cubic
- the remote-manual and converter loopback rules also classify templates
whose port is a placeholder (``http://localhost:{port}/x``), which do not
parse as URLs yet name loopback literally
- an explicit ``base_url`` override lifts the OpenAPI token-URL rule, as it
lifts the server-URL rule
- a failed WebSocket discovery closes the socket and session it opened
- README: name the override that actually exists
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 7 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
A socket already in the pool may be carrying another registration's or a tool call's traffic, so the cleanup added for failed discoveries is scoped to connections the discovery itself opened. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…arse error Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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
Loopback is the trust boundary of the HTTP plugins: plain HTTP to loopback is allowed for local development, and only for requests the user addressed there. This closes the ways a host decided after registration could still land a request on the agent's own interface, and ports the same rules to the WebSocket plugin.
utcp-http 1.1.14 → 1.1.15
ensure_loopback_was_declared).http://localhost:8080/items/{id}keeps working;http://{host}:7777/admincalled withhost=127.0.0.1is refused before any request leaves. Applied to http, SSE and streamable HTTP. Templates may still take their host from an argument for any other destination; nothing is rejected at registration for having a placeholder host.reject_remote_loopback_tool_urlsnow also refuses a loopback OAuth2token_url(the client-credentials POST is a request made on the manual's behalf). Covers GHSA-pg2m-h8f5-6ppq.tokenUrl, absolute or resolved from a relative/scheme-relative value, is refused for a spec fetched from a non-loopback origin. Covers GHSA-32vv-p32r-hxxp; flips the test that documented this gap. Server variables with adefaultare now resolved intoservers[0].url, as the OpenAPI spec intends.spec_url, so a loopback discovery URL that redirected to a remote origin does not keep the local-dev exemption (the manual path already did this).utcp-websocket 1.2.0 → 1.2.1
aiohttp.TraceConfigfails the connection on the first3xx, before the redirected request is built), so a3xxanswer can no longer steer the handshake and its auth headers at a hostensure_secure_ws_urlnever saw. Covers GHSA-6mfx-q9f2-jwx8.token_url), which it was missing.GHSA-2r98-cv5v-cj65 (redirect into loopback) was already closed in 1.1.14 (#109).
Test plan
test_remote_loopback_bypass.py(classifier table, call-time rule, remote-manual token_url, converter rules, end-to-end attack and control per protocol against an aiohttp server that records hits)test_websocket_redirect_security.py(upgrade redirect refused with the internal target never contacted and the API key never sent; direct handshake control; remote-manual rule)pytest core plugins: 626 passed, 9 skipped before the last revision; http + websocket plugins 364 passed after it🤖 Generated with Claude Code