security: fail-closed defaults for prod auth + Twilio sig#27
Merged
dougdevitre merged 1 commit intomainfrom Apr 17, 2026
Merged
security: fail-closed defaults for prod auth + Twilio sig#27dougdevitre merged 1 commit intomainfrom
dougdevitre merged 1 commit intomainfrom
Conversation
Three production-safety changes following an audit. Each mirrors the
existing fail-closed pattern in api/cron/cost-rollup.ts:
- Twilio signature validation is now ALWAYS on in production
(signatureValidationEnabled returns true when NODE_ENV=production
regardless of VALIDATE_TWILIO_SIGNATURE). Previously the env var
defaulted to "false", so a deploy without it explicitly set to "true"
accepted forged Twilio webhooks → spoofed call status, arbitrary
TwiML, and amplified Anthropic + ElevenLabs cost.
- authorizeOutbound and authorizeRecords now return 500 in production
when both OUTBOUND_API_KEY and CLERK_SECRET_KEY are unset. Previously
they fell open silently — a misconfigured prod deploy was a direct
path to billing fraud (/call/outbound) or PII leak (/records).
Non-prod still falls open as a local-dev escape hatch.
- RECORDS_TTL_DAYS is now NaN-guarded. parseFloat("abc") → NaN was
propagating into TTL timestamps as garbage; falls back to 365.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Owner
Author
Manual verification — code trace ✅All three remaining test-plan items verified by tracing the code paths:
CI green (284/286, same 2 pre-existing on |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three production-safety changes from a security pass. Each mirrors the existing fail-closed pattern in
api/cron/cost-rollup.ts.signatureValidationEnabled()now returnstruewhenNODE_ENV=productionregardless ofVALIDATE_TWILIO_SIGNATURE. Previously the env var defaulted to"false", so any deploy that didn't explicitly set it to"true"accepted forged Twilio webhooks → spoofed call status, arbitrary TwiML, and amplified Anthropic + ElevenLabs cost.OUTBOUND_API_KEYandCLERK_SECRET_KEYare unset andNODE_ENV=production, return 500 "Server misconfigured" instead of falling open. A misconfigured prod deploy was previously a direct path to billing fraud (/call/outbound) or PII leak (/records). Non-prod still falls open as a local-dev escape hatch.RECORDS_TTL_DAYSNaN guard (src/config/env.ts) —parseFloat("abc")was propagating NaN into DynamoDB TTL timestamps; now falls back to 365.Test plan
npm run typecheck— cleannpm test— 284/286 (same 2 pre-existing failures onmain, not introduced here)NODE_ENV=productionwithVALIDATE_TWILIO_SIGNATUREunset →/call/incomingrejects unsigned POSTs with 403NODE_ENV=productionwith both auth env vars unset →/call/outboundreturns 500 with{ error: "Server misconfigured" }NODE_ENV=developmentwith both auth env vars unset → still falls open (no behavior change)🤖 Generated with Claude Code