From 86cbdd4e760b2131640a9e52d47a2044e560da4b Mon Sep 17 00:00:00 2001 From: Manish Kumar Date: Fri, 14 Aug 2026 01:14:41 -0500 Subject: [PATCH] security: provision audit signing secret for security-audit + worker Problem: security-audit and security-audit-worker never received JWT_SECRET in this compose file, so two things silently fell back to the public literal "change-me" instead of the real platform secret: - security-audit's own JWT verification (api/deps.py::require_ platform_admin, audit/identity.py::validate_identity_token) - AuditConfig.EVENT_SIGNING_SECRET (audit/config.py:34, os.getenv("JWT_SECRET", "change-me")), which PR2's classify_event_integrity() uses to verify audit-event signatures Fix: both services now receive JWT_SECRET: ${AUTH_SECRET_KEY:-change-me}, the exact same variable name/value every other JWT_SECRET consumer in this file already uses (auth-service's own SECRET_KEY, api-gateway, control-center, tes, ...). No new variable introduced, no secret value added to source -- AUTH_SECRET_KEY is sourced from .env (gitignored, untracked) exactly as it already is for every other consumer. Verified live prior to this commit (hash comparison only, values never printed): security-audit's JWT_SECRET, security-audit-worker's JWT_SECRET, and auth-service's SECRET_KEY all hash identical inside their running containers. Scope: this is provisioning only. It does not add producer-side signing, run the audit-integrity DB migration, touch audit classification/ verification code, address TES work_dir isolation, or touch GHCR/release tooling -- each is a separate, later PR. Validation: - docker compose -f docker-compose.yml config --quiet: exit 0 - pytest tests/ (excl. integration): 97 passed - pytest tests/test_compose_release_config.py tests/test_compose_network_exposure.py: 71 passed (unaffected -- these cover the release compose files, not this one) - node --test tests/test_secret_generation.js: 13 passed - git diff reviewed: docker-compose.yml only, two services, both additions match the file's own established JWT_SECRET pattern Co-Authored-By: Claude Sonnet 5 --- docker-compose.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 2a99799..441f3fa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1026,6 +1026,15 @@ services: environment: PYTHONUNBUFFERED: "1" REDIS_URL: redis://redis:6379 + # Signing-secret provisioning fix: same var name/value already wired + # into every other JWT_SECRET consumer in this file (see tes's own + # entry above). Previously unset here, so this service's own JWT + # verification (api/deps.py::require_platform_admin, audit/ + # identity.py::validate_identity_token) and, as of PR2's + # AuditConfig.EVENT_SIGNING_SECRET, audit-event signature + # verification both silently fell back to the public literal + # "change-me" instead of the real platform secret. + JWT_SECRET: ${AUTH_SECRET_KEY:-change-me} # PR-B0: previously unset here, so GET /audit/events # (api/routes_audit_events.py, Depends(get_db)) fell back to # audit/config.py's default mysql+pymysql://root:root@localhost:3306/ @@ -1059,6 +1068,14 @@ services: environment: PYTHONUNBUFFERED: "1" REDIS_URL: redis://redis:6379 + # Signing-secret provisioning fix: same var name/value the API + # service above (and every other JWT_SECRET consumer in this file) + # already receives. Previously unset here, so AuditConfig. + # EVENT_SIGNING_SECRET (PR2's classify_event_integrity()) silently + # fell back to "change-me" instead of the real platform secret -- + # harmless while no producer signs, but would misclassify a real + # producer's valid signature as "invalid" once one does. + JWT_SECRET: ${AUTH_SECRET_KEY:-change-me} AUDIT_DATABASE_URL: mysql+pymysql://root:${MYSQL_ROOT_PASSWORD:-omnibioai}@mysql:3306/omnibioai_audit depends_on: redis: