Skip to content

fix(chutes): redact OAuth error response body#103569

Merged
steipete merged 5 commits into
openclaw:mainfrom
ZOOWH:fix/chutes-oauth-error-body
Jul 10, 2026
Merged

fix(chutes): redact OAuth error response body#103569
steipete merged 5 commits into
openclaw:mainfrom
ZOOWH:fix/chutes-oauth-error-body

Conversation

@ZOOWH

@ZOOWH ZOOWH commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Chutes OAuth token failures were read under a byte limit but then embedded as raw provider response text. The submitted patch addressed the legacy/core token code, while the canonical bundled Chutes plugin login path still had the same disclosure risk.

Why This Change Was Made

Route all three Chutes token operations through the existing assertOkOrThrowProviderError boundary:

  • bundled plugin authorization-code exchange
  • legacy/core authorization-code exchange
  • runtime refresh-token exchange

The shared boundary caps response reads, cancels oversized bodies, preserves HTTP/OAuth diagnostics, and stores only bounded redacted metadata. Regression tests cover structured OAuth JSON and oversized plain-text failures without calling response.text().

User Impact

Failed Chutes sign-in and refresh attempts retain actionable status and OAuth failure detail without exposing complete response bodies or credential-bearing text in thrown messages.

Evidence

  • Reviewed head: e01da19e04a8fcc91a5f10ac869ef97a34f244a7
  • Sanitized AWS Linux (cbx_97a094e99424, public network, no Tailscale): 30/30 focused tests passed and pnpm check:changed completed across core/plugin typecheck, lint, and guards in run run_d4e1bc01837d. The run's final status reflects an initially over-strict live-proof assertion about optional OAuth metadata, not a code-gate failure.
  • Corrected deployed-API proof: Crabbox run run_5cfabe9f9f53 exercised the production bundled-plugin exchange and core refresh paths against https://api.chutes.ai/idp/token; both returned normalized HTTP 400 failures with OAuth detail preserved, submitted values absent, and no raw JSON in the message.
  • Hosted exact-head CI: run 29110124722 completed successfully.
  • Fresh exact-head autoreview: clean, no accepted/actionable findings (overall: patch is correct, confidence 0.86).

Changed surface

extensions/chutes/oauth.ts
extensions/chutes/oauth.test.ts
src/agents/chutes-oauth.ts
src/agents/chutes-oauth.flow.test.ts
  • I understand what the code does
  • Change is focused and does not mix unrelated concerns

@clawsweeper re-review

@ZOOWH
ZOOWH requested a review from a team as a code owner July 10, 2026 08:36
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS labels Jul 10, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. labels Jul 10, 2026
@clawsweeper

clawsweeper Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 10, 2026, 9:21 AM ET / 13:21 UTC.

Summary
The PR changes Chutes OAuth token exchange and refresh failures to include HTTP status plus bounded, redacted structured provider details instead of raw response text, and updates the two focused failure assertions.

PR surface: Source +6, Tests 0. Total +6 across 2 files.

Reproducibility: yes. Current main directly places bounded but unredacted non-2xx response text into both Chutes OAuth error messages, and the focused flow tests reach both branches.

Review metrics: none identified.

Root-cause cluster
Relationship: canonical
Canonical: #103569
Summary: This PR is the focused candidate for the Chutes-specific raw OAuth error-body path; the related merged PRs provide feature provenance and a separate-provider precedent rather than replacing this work.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none.

Risk before merge

  • [P1] The PR head is behind current main, so maintainers should refresh it before landing even though the inspected post-base changes do not overlap the reviewed files.

Maintainer options:

  1. Decide the mitigation before merge
    Refresh the branch and land the existing shared-helper integration after normal auth/security-owner review, preserving the current timeout, bounded-read, cancellation, structured-detail, and redaction behavior.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P2] No concrete code repair remains; maintainers should refresh the behind branch and complete normal auth/security-owner review before merge.

Security
Cleared: The focused diff strengthens the OAuth sensitive-data boundary and introduces no dependency, package-resolution, permission, secret-access, code-execution, or supply-chain change.

Review details

Best possible solution:

Refresh the branch and land the existing shared-helper integration after normal auth/security-owner review, preserving the current timeout, bounded-read, cancellation, structured-detail, and redaction behavior.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main directly places bounded but unredacted non-2xx response text into both Chutes OAuth error messages, and the focused flow tests reach both branches.

Is this the best way to solve the issue?

Yes. Reusing the existing provider HTTP error parser is the narrowest maintainable fix because it centralizes bounded reads, cancellation, structured OAuth parsing, and redaction instead of adding a Chutes-specific security path.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 328eaa3a23d6.

Label changes

Label changes:

  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body provides after-fix live HTTP 400 output showing retained status, bounded structured detail, omitted raw JSON keys, and redaction of synthetic sensitive text; no further contributor proof is required.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove status: ⏳ waiting on author: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P2: This is a focused provider-specific OAuth bug that prevents potentially sensitive response content from entering thrown errors and downstream logs.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body provides after-fix live HTTP 400 output showing retained status, bounded structured detail, omitted raw JSON keys, and redaction of synthetic sensitive text; no further contributor proof is required.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body provides after-fix live HTTP 400 output showing retained status, bounded structured detail, omitted raw JSON keys, and redaction of synthetic sensitive text; no further contributor proof is required.
Evidence reviewed

PR surface:

Source +6, Tests 0. Total +6 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 12 6 +6
Tests 1 2 2 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 14 8 +6

What I checked:

  • Current-main reproduction: Current main reads a bounded but unredacted response prefix and interpolates it directly into both Chutes token exchange and refresh errors. (src/agents/chutes-oauth.ts:159, 328eaa3a23d6)
  • Canonical implementation: The PR head routes both non-2xx branches through extractProviderErrorDetail, retains HTTP status, and preserves the existing 30-second request signals. (src/agents/chutes-oauth.ts:161, 116408c6687f)
  • Shared security contract: The helper bounds the response-body read, redacts retained body and normalized detail text, extracts OAuth descriptions and codes, and returns only compact detail for this caller. (src/agents/provider-http-errors.ts:133, 328eaa3a23d6)
  • Regression coverage: The current PR head updates both previously failing assertions while retaining checks that the unbounded response.text() path is unused and oversized bodies are cancelled. (src/agents/chutes-oauth.flow.test.ts:315, 116408c6687f)
  • Prior finding resolved: Commit 48da7d2bcf1fc6ca0606940876b6a24eec065bdb changes the two assertions identified in the previous ClawSweeper cycle, so that finding no longer applies. (src/agents/chutes-oauth.flow.test.ts:338, 48da7d2bcf1f)
  • Current-main overlap check: No commits after the PR merge base modify the changed Chutes files or the shared provider-error implementation and tests, so the behind state does not establish a concrete three-way merge regression. (src/agents/chutes-oauth.ts:1, 328eaa3a23d6)

Likely related people:

  • steipete: Authored the final hardening commit for the original Chutes OAuth PR, merged that feature, and also authored the final normalization commit and merged the adjacent Copilot OAuth error-boundary fix. (role: feature hardener and merger; confidence: high; commits: f566e6451f7e, 8d640ccc6895, 66fa0e5209b1; files: src/agents/chutes-oauth.ts, src/agents/chutes-oauth.flow.test.ts, src/agents/provider-http-errors.ts)
  • FrieSei: Authored the original merged Chutes OAuth implementation and its initial flow tests, including token exchange and refresh behavior. (role: introduced behavior; confidence: high; commits: 4efb5cc18efa, 3271ff1d6e26, 8d640ccc6895; files: src/agents/chutes-oauth.ts, src/agents/chutes-oauth.flow.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (1 earlier review cycle)
  • reviewed 2026-07-10T11:41:09.937Z sha 66102d3 :: found issues before merge. :: [P2] Update the Chutes failure assertions for the new messages

@ZOOWH
ZOOWH force-pushed the fix/chutes-oauth-error-body branch from 66102d3 to 48da7d2 Compare July 10, 2026 12:48
@ZOOWH

ZOOWH commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Rebased on latest main, resolved merge conflict on import block (retained buildOAuthRequestSignal and CHUTES_OAUTH_REQUEST_TIMEOUT_MS from main), and updated the two failure-path test assertions (token exchange failed / token refresh failed) to match the new message format with status code prefix.

node scripts/run-vitest.mjs src/agents/chutes-oauth.flow.test.ts
Tests  10 passed (10)

@clawsweeper

clawsweeper Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 10, 2026
@steipete steipete self-assigned this Jul 10, 2026
@steipete
steipete force-pushed the fix/chutes-oauth-error-body branch from 116408c to 23cf0a5 Compare July 10, 2026 17:06
@steipete
steipete force-pushed the fix/chutes-oauth-error-body branch from 23cf0a5 to e01da19 Compare July 10, 2026 17:11
@steipete

Copy link
Copy Markdown
Contributor

Land-ready maintainer proof for e01da19e04a8fcc91a5f10ac869ef97a34f244a7:

  • Expanded the submitted core-only fix to the canonical bundled Chutes plugin exchange plus core exchange and refresh. All three now use the shared bounded/redacted ProviderHttpError boundary.
  • Added structured-JSON and oversized-plain-text negative controls, including response-body cancellation and assertions that full submitted values are absent from messages and stored metadata.
  • Sanitized AWS Linux (cbx_97a094e99424, public network, no Tailscale): pnpm test src/agents/chutes-oauth.flow.test.ts extensions/chutes/oauth.test.ts src/agents/provider-http-errors.test.ts passed 30/30 tests; pnpm check:changed then completed core/plugin typecheck, lint, and guards in run_d4e1bc01837d. That run's final nonzero status came only from an initially over-strict live-proof assertion about optional OAuth metadata after the code gates had completed.
  • Corrected deployed-API proof run_5cfabe9f9f53 passed against the production Chutes token endpoint through the bundled-plugin exchange and core refresh implementations: both produced normalized HTTP 400 OAuth failures, preserved useful failure detail, omitted submitted values, and did not expose raw JSON in the message.
  • Fresh exact-head autoreview: clean; no accepted/actionable findings (overall: patch is correct, confidence 0.86).
  • Exact-head hosted CI/Testbox: run 29110124722 completed successfully. OPENCLAW_TESTBOX=1 scripts/pr prepare-run 103569 accepted that evidence and verified the remote PR tree.
  • Current-main drift check: no changes since the PR merge base in any of the four touched files.

Known proof gaps: none for the changed failure path. A successful real-user OAuth grant was intentionally not attempted because it requires user credentials and does not exercise this non-2xx handling change.

@steipete
steipete merged commit 6189324 into openclaw:main Jul 10, 2026
103 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Merged via squash.

ZOOWH added a commit to ZOOWH/openclaw that referenced this pull request Jul 10, 2026
Verify that extractProviderErrorDetail bounds and redacts secrets
in error responses — matching the maintainer-upgraded pattern in
the merged chutes OAuth fix (openclaw#103569).
ZOOWH added a commit to ZOOWH/openclaw that referenced this pull request Jul 10, 2026
Same pattern as the exchange path and the merged chutes OAuth fix (openclaw#103569).
ZOOWH added a commit to ZOOWH/openclaw that referenced this pull request Jul 10, 2026
Verify that assertOkOrThrowProviderError bounds and redacts secrets in
error responses — matching the merged pattern in openclaw#103569.
ZOOWH added a commit to ZOOWH/openclaw that referenced this pull request Jul 11, 2026
Same pattern as the exchange path and the merged chutes OAuth fix (openclaw#103569).
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 11, 2026
* fix(chutes): redact OAuth error response body in token exchange and refresh

Replace readResponseTextLimited + raw body in error message with
extractProviderErrorDetail for bounded, redacted structured error detail.

Ref: openclaw#102953

* fix(chutes): update test assertions for extractProviderErrorDetail message format

* fix(chutes): remove unused readResponseTextLimited and CHUTES_OAUTH_ERROR_BODY_LIMIT_BYTES

* fix(chutes): normalize OAuth HTTP failures

* test(chutes): assert redaction without fixed mask

---------

Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling extensions: chutes P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants