Skip to content

fix(webapp): stop API auth failures leaking the controller's raw error string#3848

Open
d-cs wants to merge 1 commit into
mainfrom
fix/sanitize-auth-failure-messages
Open

fix(webapp): stop API auth failures leaking the controller's raw error string#3848
d-cs wants to merge 1 commit into
mainfrom
fix/sanitize-auth-failure-messages

Conversation

@d-cs
Copy link
Copy Markdown
Collaborator

@d-cs d-cs commented Jun 5, 2026

Summary

API auth failures returned the auth controller's raw error string verbatim in the response body. That string isn't guaranteed to be client-safe — a controller can surface an internal infrastructure error (e.g. a database connection failure) as the auth error, which then reaches the API client and is echoed by the SDK into the run view. This removes that channel: the client message is now derived purely from the HTTP status, and the controller's original string is logged server-side only.

Design

The fix sits at the single auth chokepoint every authenticated API request funnels through — the apiBuilder bearer bridge and the PAT path. Both now route failures through sanitizeAuthFailure, which maps the status to a fixed client-safe message (401 → "Invalid credentials", 403 → "Forbidden") and drops the controller's prose. Status codes, response body shape, and machine-readable fields are unchanged; only the human-readable message text changes. Granular auth hints (e.g. preview-branch header guidance) are flattened as a deliberate trade-off — full detail stays in server logs.

This is provenance-based rather than content-based: it holds regardless of what any current or future auth controller returns, so the same class of leak can't reappear through a different message string. It closes a gap left by the earlier 5xx/exception-focused passes in #3536 and #3664, which couldn't reach a value returned on a 4xx through the auth channel.

Test plan

  • Unit test: the leaked-message fixture is reduced to the status-derived message
  • e2e: bridge route returns the fixed message on auth failure (confirmed RED on pre-fix code, GREEN after)
  • Full auth e2e suites pass (api-auth, auth-api, auth-cross-cutting)

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 5, 2026

⚠️ No Changeset found

Latest commit: 2bd1bf6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a5404234-393b-40f7-881e-4cef2075b466

📥 Commits

Reviewing files that changed from the base of the PR and between 21c2ba2 and 2bd1bf6.

📒 Files selected for processing (5)
  • .server-changes/sanitize-auth-failure-messages.md
  • apps/webapp/app/services/routeBuilders/apiBuilder.server.ts
  • apps/webapp/app/services/routeBuilders/publicAuthError.ts
  • apps/webapp/test/api-auth.e2e.test.ts
  • apps/webapp/test/publicAuthError.test.ts
✅ Files skipped from review due to trivial changes (1)
  • .server-changes/sanitize-auth-failure-messages.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/webapp/app/services/routeBuilders/publicAuthError.ts
  • apps/webapp/test/api-auth.e2e.test.ts
  • apps/webapp/test/publicAuthError.test.ts
  • apps/webapp/app/services/routeBuilders/apiBuilder.server.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp
  • GitHub Check: typecheck / typecheck
  • GitHub Check: 🛡️ E2E Auth Tests (full)

Walkthrough

This PR centralizes auth-failure sanitization and applies it to API bearer and PAT auth paths. A new module defines AuthFailureStatus (401|403), publicAuthError(status) mapping, and sanitizeAuthFailure(failure). apiBuilder.server.ts imports and uses sanitizeAuthFailure to log raw errors server-side and return only status-derived error messages to clients. Tests (unit and E2E) verify sanitized messages, and a server-changes note documents the update.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main security fix: preventing API auth failures from leaking the controller's raw error string to clients.
Description check ✅ Passed The description comprehensively covers the problem, design approach, and testing, though it does not strictly follow the repository's PR description template structure.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sanitize-auth-failure-messages

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: dependency version conflict. Check your lock file or package.json.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@d-cs d-cs self-assigned this Jun 5, 2026
…r string

Auth controllers (the OSS RBAC fallback and the cloud RBAC plugin) return an
`error` string on failure that the apiBuilder forwarded verbatim into the
response body. A controller can conflate an infrastructure failure with an
auth rejection — when the database is unreachable the plugin's key lookup
throws a Prisma error ("Can't reach database server at <prod RDS hostname>")
and returns it as the auth error. The SDK then surfaced that string in the
customer's run view via TriggerApiError, leaking internal infra detail.

This evaded the two prior leak fixes because both were scoped to exceptions
on 5xx responses; this leak is a returned value on a 4xx through the auth
channel.

Sanitize at the single auth chokepoint: derive the client message purely
from the status (401 -> "Invalid credentials", 403 -> "Forbidden") and log
the controller's raw string server-side. Applied to both the bearer bridge
and the PAT path. Status codes, body shape, and machine-readable fields are
unchanged; only the human-readable message text changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@d-cs d-cs force-pushed the fix/sanitize-auth-failure-messages branch from 21c2ba2 to 2bd1bf6 Compare June 5, 2026 15:15
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jun 5, 2026

Open in StackBlitz

@trigger.dev/build

npm i https://pkg.pr.new/@trigger.dev/build@2bd1bf6

trigger.dev

npm i https://pkg.pr.new/trigger.dev@2bd1bf6

@trigger.dev/core

npm i https://pkg.pr.new/@trigger.dev/core@2bd1bf6

@trigger.dev/plugins

npm i https://pkg.pr.new/@trigger.dev/plugins@2bd1bf6

@trigger.dev/python

npm i https://pkg.pr.new/@trigger.dev/python@2bd1bf6

@trigger.dev/react-hooks

npm i https://pkg.pr.new/@trigger.dev/react-hooks@2bd1bf6

@trigger.dev/redis-worker

npm i https://pkg.pr.new/@trigger.dev/redis-worker@2bd1bf6

@trigger.dev/rsc

npm i https://pkg.pr.new/@trigger.dev/rsc@2bd1bf6

@trigger.dev/schema-to-json

npm i https://pkg.pr.new/@trigger.dev/schema-to-json@2bd1bf6

@trigger.dev/sdk

npm i https://pkg.pr.new/@trigger.dev/sdk@2bd1bf6

commit: 2bd1bf6

@d-cs d-cs marked this pull request as ready for review June 5, 2026 15:30
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant