Skip to content

security(lims): fix DJANGO_DEBUG drift in docker-compose-release.yml - #46

Merged
man4ish merged 1 commit into
mainfrom
security/hipaa-lims-release-debug-drift
Aug 14, 2026
Merged

security(lims): fix DJANGO_DEBUG drift in docker-compose-release.yml#46
man4ish merged 1 commit into
mainfrom
security/hipaa-lims-release-debug-drift

Conversation

@man4ish

@man4ish man4ish commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to PR #44/#45 (HIPAA Studio compose hardening audit) — closes the lims DEBUG drift flagged during that audit and deliberately left out at the time.

Finding: docker-compose-release.yml (dash-named) still shipped DJANGO_DEBUG: "true" for the lims service, with FIELD_ENCRYPTION_KEY entirely absent.

Proof of effectiveness (not just presence):

  • omnibioai-lims/lab_data_manager/settings.py:29 reads DJANGO_DEBUG directly from the environment (env.bool("DJANGO_DEBUG", ...)) with no override.
  • The LIMS Dockerfile's persistent ENV layer deliberately omits DJANGO_DEBUG (comment: "Never set it to true in the persistent ENV layer") — the only place the image sets it is a transient RUN DJANGO_DEBUG=true ... collectstatic build-time step, which does not affect the runtime container.
  • No entrypoint/supervisord override exists.
  • ⇒ whatever the compose file sets is the runtime Django DEBUG value. This was a live, effective drift, not dead configuration.

Root cause: commit 951ad25 ("disable prod DEBUG, wire up FIELD_ENCRYPTION_KEY") fixed docker-compose.release.yml (dot) and docker-compose.yml (dev) but missed the dash file.

Deployment-path scoping — why this isn't a live exposure in the shipped installer:

  • electron-builder.json and electron/main.js's getComposeFilePath() only ever reference docker-compose.release.yml (dot) or docker-compose.yml (dev) — never the dash file. Confirmed by direct inspection, not inference.
  • SECURITY-COMPOSE-HARDENING.md §6 already documents docker-compose-release.yml as "not the shipped artifact... kept in [credential/exposure] parity" with the dot file — this PR closes exactly that parity gap.
  • The only workflow that ever published the dash file as a downloadable release artifact (.github/workflows/disabled/release.yml) lives outside .github/workflows/'s auto-discovered root and is not referenced by any active workflow — GitHub Actions does not run it.
  • Net effect: this is a real, fixable drift in a file the project maintains as a parity twin of the shipped config — not a currently-exploitable exposure in the packaged product.

Fix: minimal, matches the already-established convention exactly (same pairing the dot-file fix already uses) rather than inventing anything new:

-      DJANGO_DEBUG: "true"
+      DJANGO_DEBUG: "false"
       ...
+      FIELD_ENCRYPTION_KEY: ${LIMSX_FIELD_ENCRYPTION_KEY}

FIELD_ENCRYPTION_KEY is required alongside the DEBUG flip: settings.py raises RuntimeError("FIELD_ENCRYPTION_KEY must be set in non-debug environments") once DEBUG=False, so flipping DEBUG alone (without wiring the key) would have crash-looped the container. Verified via docker compose config with dummy secrets — resolves cleanly, DJANGO_DEBUG: "false" and FIELD_ENCRYPTION_KEY interpolate correctly.

Out of scope (per audit brief, not touched): HOST_IP bindings, LIMS auth/tenant isolation, other services' credentials, the broader HOST_IP architecture question.

Test plan

  • New tests/test_lims_debug_config.py, parametrized over both release compose files + the dev compose as parity source of truth (mirrors test_compose_release_config.py's approach to the JWT-secret drift between the same two files).
  • Confirmed the new tests fail against the pre-fix dash file (git stash + rerun) — both DJANGO_DEBUG and FIELD_ENCRYPTION_KEY assertions catch the original bug.
  • docker compose --env-file <dummy-secrets> -f docker-compose-release.yml config resolves cleanly; lims block shows DJANGO_DEBUG: "false" and FIELD_ENCRYPTION_KEY interpolated.
  • Full repo test suite compared exact failure/error ID sets (not aggregate counts) between clean origin/main (d809a0a) and this branch: identical 51 failed + 22 errored IDs on both (pre-existing, unrelated — require live services). This branch adds 178 passed vs. baseline's 173 passed (+5 = the new test file), zero regressions.
  • SECURITY-COMPOSE-HARDENING.md §7 updated with a dated remediation note (matching the existing control-center follow-up entry's style) recording the drift, the proof it was effective, and why it's not a shipped-installer exposure.

🤖 Generated with Claude Code

The dash-named release compose file still shipped DJANGO_DEBUG: "true"
for lims, with FIELD_ENCRYPTION_KEY entirely absent -- both missed by
951ad25, which fixed docker-compose.release.yml (the file electron-builder
actually bundles) and docker-compose.yml (dev) but not this one.

lab_data_manager/settings.py reads DJANGO_DEBUG directly from the
environment with no override anywhere in the image (confirmed via
Dockerfile/entrypoint/supervisord), so this was a live, effective drift,
not dead configuration. Not reachable through the packaged Electron app's
startup path (electron/main.js never resolves to the dash file) -- this
closes a parity gap in a file SECURITY-COMPOSE-HARDENING.md already
documents as "kept in parity," not a live exposure in the shipped
installer.

Fixed to match the dot file exactly (DJANGO_DEBUG: "false" +
FIELD_ENCRYPTION_KEY sourced from LIMSX_FIELD_ENCRYPTION_KEY, the same
convention DJANGO_SECRET_KEY already uses) rather than inventing a new
mechanism. Adds tests/test_lims_debug_config.py, parametrized over both
release files plus the dev compose as the parity source of truth, so this
specific drift -- and the crash-loop that flipping DEBUG alone without
FIELD_ENCRYPTION_KEY would cause -- can't silently reappear.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@man4ish
man4ish merged commit 23144ef into main Aug 14, 2026
7 checks passed
@man4ish
man4ish deleted the security/hipaa-lims-release-debug-drift branch August 14, 2026 01:24
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