Skip to content

fix(security): Wave 1 — token TTL, Sentry gaps, backup hygiene, GDPR consent audit#180

Merged
gerfru merged 4 commits into
mainfrom
fix/wave-1-security-observability
Jun 10, 2026
Merged

fix(security): Wave 1 — token TTL, Sentry gaps, backup hygiene, GDPR consent audit#180
gerfru merged 4 commits into
mainfrom
fix/wave-1-security-observability

Conversation

@gerfru

@gerfru gerfru commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Summary

Security & Observability hardening — all 7 Wave 1 findings from the 2026-06-10 app review.

  • H1 api/src/mail.py — Fix email TTL text: reset "1 Stunde" → "15 Minuten", deletion "24 Stunden" → "1 Stunde" (token reality)
  • H2 env/.env.app — Add SENTRY_DSN so sync-service and ml-service report runtime errors (was api-only)
  • H3 backup/Dockerfile — Pin base image to postgres:16-alpine@sha256:… digest (all 3 app images were already pinned)
  • H4 .github/workflows/ci.yml — Add backup image Trivy CRITICAL/HIGH scan to CI
  • M4 api/src/routes/account.py — Remove raw deletion-confirm token from log output (secret-in-log)
  • C1 db/migrations/V27__user_consent_events.sql + api/src/db/users.py — GDPR Art. 5(2) consent audit table; save_consent dual-write in asyncpg transaction; fix privacy_policy_version not updated on re-consent
  • L9 api/src/routes/api_seizures.py — Gate all 5 seizure endpoints behind epilepsy_mode guard (403 when disabled); update tests to TEST_USER_EPILEPSY

Test plan

  • pytest api/tests/ --ignore=tests/e2e → 438 passed, 0 failed
  • mypy api/src/ → no issues (34 source files)
  • pre-commit run ruff --all-files → Passed
  • All pre-commit hooks green on commit
  • e2e idor_seizure_pair fixture: attacker gets epilepsy_mode=TRUE so DB ownership isolation is exercised (not short-circuited by mode guard)

🤖 Generated with Claude Code

gerfru and others added 4 commits June 10, 2026 14:36
…consent audit

H1: fix reset/deletion email TTL text (was "1 Stunde"/"24 Stunden", now "15 Minuten"/"1 Stunde")
H2: add SENTRY_DSN to env/.env.app so sync-service and ml-service report errors
H3: pin backup/Dockerfile base image to postgres:16-alpine digest
H4: add backup image build + Trivy CRITICAL/HIGH scan to CI
M4: remove raw deletion-confirm token from account.py log output (secret-in-log)
C1: V27 migration — user_consent_events audit table (GDPR Art. 5(2) accountability);
    save_consent dual-write with asyncpg transaction; fix privacy_policy_version not updated on re-consent
L9: gate all 5 seizure endpoints behind epilepsy_mode guard (403 when mode disabled);
    update tests to use TEST_USER_EPILEPSY fixture

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hip check

After L9 fix (epilepsy_mode guard on all seizure endpoints), the attacker
user in idor_seizure_pair had epilepsy_mode=FALSE — causing 403 before the
DB-level ownership filter could run and return 404. Both users now have
epilepsy_mode=TRUE so the cross-user isolation is actually exercised.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
apk upgrade --no-cache fixes CVE-2026-6732 (libxml2, HIGH, fixed in 2.13.9-r1).

gosu is a pre-compiled Go binary in postgres:16-alpine; CVEs are in its bundled
Go stdlib (v1.24.6). We don't call gosu anywhere — backup scripts run as the
postgres user directly. Suppressed via backup/.trivyignore with rationale comment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gerfru gerfru merged commit 0719fc8 into main Jun 10, 2026
12 checks passed
@gerfru gerfru deleted the fix/wave-1-security-observability branch June 10, 2026 13:26
gerfru added a commit that referenced this pull request Jun 12, 2026
…consent audit (#180)

* fix(security): Wave 1 — token TTL, Sentry gaps, backup hygiene, GDPR consent audit

H1: fix reset/deletion email TTL text (was "1 Stunde"/"24 Stunden", now "15 Minuten"/"1 Stunde")
H2: add SENTRY_DSN to env/.env.app so sync-service and ml-service report errors
H3: pin backup/Dockerfile base image to postgres:16-alpine digest
H4: add backup image build + Trivy CRITICAL/HIGH scan to CI
M4: remove raw deletion-confirm token from account.py log output (secret-in-log)
C1: V27 migration — user_consent_events audit table (GDPR Art. 5(2) accountability);
    save_consent dual-write with asyncpg transaction; fix privacy_policy_version not updated on re-consent
L9: gate all 5 seizure endpoints behind epilepsy_mode guard (403 when mode disabled);
    update tests to use TEST_USER_EPILEPSY fixture

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* delete redesign file and added coverage

* fix(test): e2e IDOR attacker needs epilepsy_mode=TRUE to reach ownership check

After L9 fix (epilepsy_mode guard on all seizure endpoints), the attacker
user in idor_seizure_pair had epilepsy_mode=FALSE — causing 403 before the
DB-level ownership filter could run and return 404. Both users now have
epilepsy_mode=TRUE so the cross-user isolation is actually exercised.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ci): backup Trivy — apk upgrade for libxml2 + trivyignore for gosu

apk upgrade --no-cache fixes CVE-2026-6732 (libxml2, HIGH, fixed in 2.13.9-r1).

gosu is a pre-compiled Go binary in postgres:16-alpine; CVEs are in its bundled
Go stdlib (v1.24.6). We don't call gosu anywhere — backup scripts run as the
postgres user directly. Suppressed via backup/.trivyignore with rationale comment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant