Repository navigation
Return the response on a failed http_request, not just its status code - #53
Conversation
`format_response` built the status line, headers and body, then threw all of it
away on a non-2xx and returned the bare string `HTTP <code>`.
Observed as `HTTP 403`, twenty characters, repeated eight times. The discarded
body was the only part that said what was wrong — GitHub's 403 names the
missing `User-Agent` header outright, with a documentation link — so the caller
had nothing to act on and the failure was misread as a credentials problem.
Also fixes the header block, which printed each name twice (`{}: {:?}` over
`(k.as_str(), k.as_str())`), so every line read
`x-ratelimit-remaining: "x-ratelimit-remaining"` and carried no information.
Values are shown now, with the existing `set-cookie` redaction widened to
anything cookie- or authorization-shaped.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tiny Sweeper reviewTiny Sweeper completed its review; deterministic results follow. State: Ready for maintainer review Review snapshot
Completeness: Complete What changedNo supported behavioral explanation was produced. Features
TestsNo supported feature-to-test mapping was produced. Test execution is not inferred. FindingsNo active actionable findings. Resolved this pass
Before mergeNone. How this fits togetherflowchart LR
n0["HttpRequestTool<br/>changed"]:::changed
n1["..._is_returned_as_the_error_without_a_retry<br/>changed"]:::changed
n2["..._success_response_is_reported_as_an_error<br/>changed"]:::changed
n3["test_tool"]:::impacted
n4["execute_request"]:::impacted
n5["format_response"]:::impacted
n6["serve"]:::impacted
n7["PaymentHook"]:::impacted
n8["handle_payment_required"]:::impacted
n0 -->|uses| n7
n1 -->|calls| n3
n1 -->|tests| n3
n1 -->|calls| n4
n1 -->|tests| n4
n1 -->|calls| n6
n1 -->|tests| n6
n1 -->|uses| n7
n1 -->|calls| n8
n1 -->|tests| n8
n2 -->|calls| n3
n2 -->|tests| n3
n2 -->|calls| n4
n2 -->|tests| n4
n2 -->|calls| n5
n2 -->|tests| n5
n2 -->|calls| n6
n2 -->|tests| n6
n3 -->|uses| n0
n8 -->|calls| n4
n8 -->|uses| n7
classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Agent review detailscritique
security
tests
commits
description
e2e
Evidence and run details
|
|
Warning Review limit reached
This review includes 2 billable files and costs up to $0.50. Or wait 53 minutes for your next included review. View limit detailsLimit details: You’ve used the included review currently available. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (2)
Comment |
There was a problem hiding this comment.
Requesting changes: 1 lane(s) blocking, worst finding is high.
Fix or reply to the findings below and push. The next review clears this automatically once they are gone — you should not need to dismiss anything by hand.
$0.0041 · 82,395 in / 6,317 out · 9,604 cached (12%) · gpt-5.6-luna, glm-5.3-flash
critique: $0.0013 · 18,528 in / 1,918 out · 2,116 cached (11%) · gpt-5.6-luna
security: $0.0027 · 49,471 in / 2,516 out · 7,488 cached (15%) · gpt-5.6-luna
tests: $0.0001 · 5,355 in / 580 out · 0 cached (0%) · glm-5.3-flash
description: $0.0000 · 5,310 in / 162 out · 0 cached (0%) · glm-5.3-flash
Response headers were previously redacted only when their name contained "cookie" or "authorization", which let credentials leak through service-specific headers with arbitrary names. Header values are now shown only for a small allowlist of diagnostic headers, and everything else is redacted. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformatted the safe response header test to satisfy rustfmt line length limits. No behaviour change. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The safe-header check was negated, so diagnostic headers were redacted while untrusted headers were exposed. The branches are swapped so only allowlisted headers have their values shown. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Extend the response formatting test to include WWW-Authenticate, X-Api-Key and X-Service-Token headers, asserting their values are redacted and the raw secrets never appear in the output. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
There was a problem hiding this comment.
The previously-blocking findings are resolved. Clearing the changes request.
$0.0105 · 118,181 in / 4,539 out · 9,848 cached (8%) · gpt-5.6-luna, glm-5.3-flash
critique: $0.0050 · 41,189 in / 1,313 out · 4,232 cached (10%) · gpt-5.6-luna
security: $0.0052 · 54,248 in / 1,103 out · 5,616 cached (10%) · gpt-5.6-luna
tests: $0.0001 · 6,621 in / 240 out · 0 cached (0%) · glm-5.3-flash
description: $0.0001 · 6,576 in / 176 out · 0 cached (0%) · glm-5.3-flash
Problem
format_responsebuilds the status line, headers and body — then discards all of it on a non-2xx:Observed in a live agent run as
HTTP 403— twenty characters — eight times in a row. The body that was thrown away said exactly what was wrong:The caller had nothing to act on, and the failure was read downstream as an authentication problem — which it was not.
A second bug in the same block: the header line printed each name twice rather than name and value —
so every entry read
x-ratelimit-remaining: "x-ratelimit-remaining". Theset-cookieredaction sitting beside it only makes sense if values were meant to be shown, which is the reading taken here.Change
outputon both armsset-cookieto anything cookie- or authorization-shaped, since a response can hand back credentialsTesting
cargo test -p tinytools-std --lib network::— 91 passed, 0 failed.The existing contract test is rewritten against the module's real loopback server, now serving a genuine
403with a body and a rate-limit header, and asserts all three properties:cargo fmt -p tinytools-std -- --checkclean.Risk
Low, but it is a visible change: failures now carry the status line, headers and body instead of
HTTP <code>. That is longer output on an error path, and the previously-pinnedcontains("HTTP 500")assertion no longer holds — hence the rewritten test. Header values are newly exposed, which is why the redaction list was widened at the same time.🤖 Generated with Claude Code