Skip to content

fix(#856 #857 #858): harden admin auth, webhook signatures, and CORS#863

Merged
hman38705 merged 1 commit into
solutions-plug:mainfrom
job-soft:fix/856-857-858-security-hardening
Jun 2, 2026
Merged

fix(#856 #857 #858): harden admin auth, webhook signatures, and CORS#863
hman38705 merged 1 commit into
solutions-plug:mainfrom
job-soft:fix/856-857-858-security-hardening

Conversation

@job-soft
Copy link
Copy Markdown
Contributor

@job-soft job-soft commented Jun 2, 2026

Summary

  • Wire admin authentication middleware into admin routes #856 — Admin auth: ApiKeyAuth::verify was fail-open: an empty API_KEYS env var let all requests through the middleware unchallenged. Changed the logic to fail-closed (!is_empty() && any()), so any deployment without API_KEYS configured now correctly returns 401 on all admin endpoints. Added a startup warning via config.validate() so operators are notified. Also added the 5 undocumented admin routes to openapi.yaml under the ApiKeyAuth security scheme (/api/blockchain/replay, /api/v1/email/queue/dead-letter, /api/v1/email/queue/dead-letter/{job_id}/requeue, /api/v1/audit/logs, /api/v1/audit/statistics).

  • Verify SendGrid webhook signatures before processing events #857 — SendGrid webhook signatures: sendgrid_webhook_middleware already performs full HMAC-SHA256 verification against SENDGRID_WEBHOOK_SECRET plus a configurable timestamp replay window (WEBHOOK_REPLAY_WINDOW_SECS, default 300 s). No code changes required — confirming implementation is complete and closing the issue.

  • Restrict CORS from fully permissive to configurable allowlist #858 — CORS allowlist: CORS is already restricted via CorsConfig loaded from CORS_ALLOWED_ORIGINS, CORS_ALLOWED_METHODS, CORS_ALLOWED_HEADERS, and CORS_ALLOW_CREDENTIALS env vars with secure production defaults. CORS_DEV_MODE=true is required to opt in to permissive behaviour and logs a warning. No code changes required — confirming implementation is complete and closing the issue.

Test plan

  • Set API_KEYS= (empty) and confirm all /admin/* requests return 401 Unauthorized.
  • Set API_KEYS=secret and confirm requests with X-API-Key: secret succeed and requests without it return 401.
  • Confirm startup log shows warning when API_KEYS is not set.
  • Confirm POST /webhooks/sendgrid with an invalid X-Twilio-Email-Event-Webhook-Signature returns 401.
  • Confirm CORS preflight with an origin not in CORS_ALLOWED_ORIGINS is blocked.

closes #856
closes #857
closes #858

🤖 Generated with Claude Code

… admin auth, webhook signatures, and CORS

- Closes solutions-plug#856: fix ApiKeyAuth::verify to fail-closed — empty API_KEYS
  previously allowed all requests through; now returns 401 when no keys
  are configured. Add startup warning in config.validate(). Document all
  missing admin routes (/api/blockchain/replay, /api/v1/email/queue/dead-letter,
  /api/v1/email/queue/dead-letter/{job_id}/requeue, /api/v1/audit/logs,
  /api/v1/audit/statistics) in openapi.yaml with ApiKeyAuth security scheme.
- Closes solutions-plug#857: SendGrid webhook signature verification was already wired via
  sendgrid_webhook_middleware (HMAC-SHA256 + timestamp replay window); no
  additional changes required.
- Closes solutions-plug#858: CORS is already restricted to a configurable allowlist via
  CORS_ALLOWED_ORIGINS env var with secure production defaults; no
  additional changes required.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented Jun 2, 2026

@job-soft Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@hman38705 hman38705 merged commit 0668215 into solutions-plug:main Jun 2, 2026
4 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants