What's Changed
- fix(security): sandbox case-report template rendering (GHSA-7q83-228r-wfh5) by @taylorwalton in #936
- fix(security): restrict data-store upload route to admin/analyst (GHSA-6j26-wcv6-gp3f) by @taylorwalton in #937
- fix(security): render user-submitted fields as text to kill stored XSS (GHSA-8hqj-cqcc-5f6w) by @taylorwalton in #938
- fix(security): fail closed on webhook header secrets (GHSA-x8gc-f8p4-frc2) by @taylorwalton in #939
⚠️ Breaking: webhook header secrets now required (security fix GHSA-x8gc-f8p4-frc2)
Previously, the Graylog and Velociraptor webhook routes authenticated against a header secret that silently fell back to a hardcoded default (ab73de7a-…) shipped in .env.example. That default is publicly known, so any deployment that never overrode it was reachable without authentication. This release removes the default — the secrets now fail closed: if unset, the routes return 403 for everyone.
Affected routes:
- POST /api/graylog/invoke (active-response invocation)
- POST /api/incidents/alerts/create/threshold (alert injection)
- POST /api/incidents/alerts/create/velo-sigma (alert injection)
Action required before/at upgrade — for ALL operators (the default value no longer works):
- Generate a unique secret for each (don't reuse one across both):
openssl rand -hex 32 # run once per secret - Set them in your .env:
GRAYLOG_API_HEADER_VALUE=
VELOCIRAPTOR_API_HEADER_VALUE= - (GRAFANA_API_HEADER_VALUE already worked this way — no change there.)
- Recreate the backend so it picks up the env vars:
docker compose up -d --force-recreate copilot-backend - Update the sending side to send the matching value:
- Graylog → the HTTP Notification for active-response and the threshold/velo-sigma alert webhooks must send header Graylog: <GRAYLOG_API_HEADER_VALUE>.
- Velociraptor → the velo-sigma alert webhook must send header Velociraptor: <VELOCIRAPTOR_API_HEADER_VALUE>.
Symptom if you miss this: active-response stops firing and Graylog/Velociraptor-sourced alerts stop being created, with 403 "… header authentication is not configured" (secret unset) or 403 "Invalid or missing … header" (mismatch) in the backend logs.
Security note: if your deployment was running with the old default, treat it as having had these endpoints exposed — rotate to a fresh secret now (don't just copy the old default into the env var).
Minor: the webhook COMMAND field is now validated to a safe script-name format ([A-Za-z0-9_-], ≤64 chars). Standard and custom active-response script names are unaffected; only names containing spaces/shell metacharacters/path separators are rejected.
Full Changelog: v0.1.75...v0.1.76