Repository navigation
fix(cli): refuse cross-origin redirects so credentials stay with the configured server - #137
TristanSpeakEasy wants to merge 3 commits into
Conversation
…configured server
There was a problem hiding this comment.
1 issue found across 7 files
Confidence score: 2/5
- In
templates/templates/cli/auxiliary/internal/client/client.go.stmpl, test mode usesTestHTTPClient, which can forward API-key headers across cross-origin redirects. Apply the protected client's redirect policy to the test client.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="templates/templates/cli/auxiliary/internal/client/client.go.stmpl">
<violation number="1" location="templates/templates/cli/auxiliary/internal/client/client.go.stmpl:87">
P1: Test mode bypasses this redirect policy: `NewClient` replaces the protected client with `TestHTTPClient`, whose underlying client follows cross-origin redirects and can forward API-key headers. Apply the same policy to the test client and cover the path through `NewClient`.</violation>
</file>
Shadow auto-approve: would not auto-approve because issues were found.
View guided diff | Turn on auto-fix | Re-trigger cubic
There was a problem hiding this comment.
0 issues found across 5 files (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would not auto-approve. Auto-approval blocked by 1 unresolved issue from previous reviews.
View guided diff | Turn on auto-fix | Re-trigger cubic
|
Verified the fix on a generated CLI against two local servers on different hostnames: 301, 302, 307 and 308 from the configured origin to the other host are refused, the custom credential header never reaches the second host, and GET operations are covered as well. Two things before merge, both in the same
Agree with leaving the test client as is; it only exists under the test harness. |
…y refused redirects as protocol errors
|
@AshGodfrey thanks, both done in 14793e0 (replying to #137 (comment)):
|
There was a problem hiding this comment.
0 issues found across 7 files (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would auto-approve. Fixes a credential leak in the generated CLI by refusing cross-origin and method-changing redirects, with focused tests for the redirect policy and error classification; the dismissed test-client caveat is confined to the generated test harness, not user CLI paths.
View guided diff | Turn on auto-fix | Re-trigger cubic
Why
The generated CLI's HTTP client used the
net/httpdefault redirect policy. On a redirect to another host,net/httpstripsAuthorizationandCookiebut forwards every other header, so an API key sent in a custom header (for examplex-api-key) reached the new host. On 307/308 the request body was replayed as well, and anhttpstohttpredirect would send the key in cleartext.The default server URL is unlikely to redirect off-origin, so this mostly matters when
--server-urlpoints at a proxy, gateway or a mistyped host. Either way the CLI should never forward credentials to a server the user did not configure.What changed
internal/clientnow setsCheckRedirecttoSameOriginRedirect. Redirects that keep the scheme, host and port (an explicit:443/:80counts as the default) are still followed (up to 10). Anything else fails with an error naming both origins, for examplerefusing to follow a redirect from https://api.example.com to http://other.example.com: credentials are only sent to the configured server.net/httpturns a POST answered with 301/302/303 into a bodiless GET, so the CLI used to print the response to a different read request and exit 0. 307 and 308 keep the method and body and are still followed.RedirectRefusedError, classified asprotocol_error/CLI_PROTOCOLwith its own hint, instead ofconnection_errorwith network-connectivity hints.internal/client/client_test.gocovers a same-origin 307 (method and body kept), a same-origin 303 on a POST (refused), a cross-origin 307 with two local servers (the credential header never reaches the second server), the origin comparison cases, and the error classification.Testing
TARGET=review make test-cliandTARGET=primary make test-cli: pass, including the new tests.make check-template-cli: passes.Public-safety check
.claude/skills/public-repo-communication/SKILL.md).git diff --check.Summary by cubic
Fixes a credential leak in the generated CLI:
net/http's default redirect policy forwards custom headers like an API key to the redirect target, which could be a different host or a scheme downgrade. The CLI now refuses redirects to a different scheme, host, or port, so credentials are only ever sent to the server the user configured; same-origin redirects still work (up to 10) and explicit default ports are treated as the same origin. A new test covers both behaviors and asserts the API key never reaches the second server.Written for commit 9809f79. Summary will update on new commits.