fix(supervisor): authorize the dequeue route and reject absent tokens in enforce mode - #4898
Conversation
… in enforce mode The workload server's dequeue route never called authorizeWorkloadRequest, and enforce mode only rejected present-but-invalid deployment tokens (jwt_invalid), letting requests with no token header at all (token_absent) through. Guard the dequeue route like the other workload-action routes and fail token_absent when WORKLOAD_TOKEN_ENFORCEMENT=enforce.
|
|
Hi @AUTHENSOR, thanks for your interest in contributing! This project requires that pull request authors are vouched, and you are not in the list of vouched users. This PR will be closed automatically. See https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md for more details. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (1)
WalkthroughThe workload server now rejects absent or invalid tokens when token enforcement is enabled. The deployment dequeue route now uses ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Devin Review found 2 potential issues.
1 security issue not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)
| const result = await verifyDeploymentIdHeader(this.deploymentIdFromRequest(req), "http"); | ||
|
|
||
| if (result.outcome === "jwt_invalid" && workloadTokenEnforced) { | ||
| if (workloadTokenEnforced && (result.outcome === "jwt_invalid" || result.outcome === "token_absent")) { |
| const result = await verifyDeploymentIdHeader(this.deploymentIdFromRequest(req), "http"); | ||
|
|
||
| if (result.outcome === "jwt_invalid" && workloadTokenEnforced) { | ||
| if (workloadTokenEnforced && (result.outcome === "jwt_invalid" || result.outcome === "token_absent")) { |
|
Closed by the vouch bot — understood, I hadn't been vouched. The PR contains a reproducible runner-boundary authorization fix (unguarded dequeue route + absent-token bypass of |
Summary
The supervisor's workload server is the trust boundary between tenant task code and the run data plane: runners connect to it to dequeue and start run attempts, and it serves the run payload plus the environment's env vars. While auditing a self-hosted (k8s/docker) deployment, three gaps line up so that anything network-adjacent to the workload server can pull runs and their secrets from other deployments without any credentials:
WORKLOAD_TOKEN_ENFORCEMENTdefaults to disabled, and the helm chart doesn't expose an override — so stock self-hosted deployments ship with no workload-token requirement at all.WORKLOAD_TOKEN_ENFORCEMENT=enforce, a request with no token header at all passes:authorizeWorkloadRequestonly rejectedjwt_invalid(a present-but-invalid token);token_absentwas accepted, so simply omitting the header bypassed enforcement entirely.GET /api/v1/workload-actions/deployments/:deploymentId/dequeue) never calledauthorizeWorkloadRequestat all — unguarded in every mode.With those three in place, an unauthenticated
attempts/startordequeue(knowing only run + snapshot friendly IDs) returns the run payload and the environment's env vars. From a PoC harness against a stock-config supervisor with a stubbed worker client:Because the request was never verified, the supervisor forwards no environment id upstream, so the platform serves the env vars unscoped rather than scoped to the caller's environment.
What this PR changes
Two changes in
apps/supervisor/src/workloadServer/index.ts— the code-level guard only:authorizeWorkloadRequestand answers401when it fails, like the other workload-action routes.token_absentis rejected alongsidejwt_invalid. Enforce mode means the operator has explicitly opted in, so failing requests with no token header is what "enforce" promises. The doc comment onauthorizeWorkloadRequestis updated to match.Behavior in the default (unenforced) mode is unchanged — this PR does not turn enforcement on.
Deliberately not changed (flagging for maintainers)
The remaining exposure is a deployment-default / product-policy question rather than a code bug, so I didn't change it unilaterally:
legacy_bare, a bare friendlyId from a pre-upgrade runner) still pass in enforce mode, for the same upgrade-compatibility reason.Happy to follow up with a helm value for
WORKLOAD_TOKEN_ENFORCEMENTif you want one.Testing
WorkloadServerwith a stubbed worker client, no real credentials) shows both routes answering 200 with env vars before the fix, and 401 in enforce mode after it; the default-mode path is unchanged.oxlinton the changed file: clean.