sec(enterprise): SECURITY.md + auth-leak fix + telemetry opt-out + stable Flask key#40
Open
dgokeeffe wants to merge 1 commit into
Open
sec(enterprise): SECURITY.md + auth-leak fix + telemetry opt-out + stable Flask key#40dgokeeffe wants to merge 1 commit into
dgokeeffe wants to merge 1 commit into
Conversation
…able Flask key
Bundle of four enterprise-readiness improvements from an independent
security review against NAB (APRA / CPS 234) and Coles (PCI-DSS / ISO
27001) procurement requirements.
E-2: Add .github/SECURITY.md (P0 compliance blocker)
================================================================
Vendor security assessments (SIG / CAIQ) ask "do you have a documented
vulnerability disclosure process?" — answer was no. Now we have:
- Two private disclosure channels (GitHub Security Advisories + email)
- Acknowledgement / triage / fix-plan / disclosure timeline
- Severity-based patch SLA (Critical: 7d, High: 14d, Medium: 30d)
- Scope boundaries (in/out of scope)
- Supply-chain controls summary for procurement reviewers
- Pointer to docs/enterprise.md § known limits for the trade-offs
we've deliberately accepted
E-4: Remove /api/app-state from auth-exempt list (P1)
================================================================
app.py:808 — /api/app-state was in the same exempt list as /health.
Unauthenticated callers could fetch app_owner email + last_rotation_iso
+ owner_resolved_at, which is enough to fingerprint session timing and
identify the workspace owner.
The endpoint has no pre-auth use case in the UI (the polling endpoints
the UI needs before PAT setup are /api/setup-status and /api/pat-status,
both still exempt). Removed from the list.
Tests:
- test_app_state_denied_for_non_owner — non-owners get 403
- test_app_state_allowed_for_owner — owner still gets 200
E-9: Telemetry opt-out via CODA_TELEMETRY_DISABLED (P2)
================================================================
telemetry.py — log_telemetry() now short-circuits when
CODA_TELEMETRY_DISABLED is truthy. Default behaviour unchanged (telemetry
still on by default).
Why this matters for procurement: regulated customers (banks, retailers
with PCI-DSS) must inventory every outbound data flow from their
workspace boundary. CoDA's User-Agent-header telemetry to Databricks
servers was previously undisclosed and unsuppressible. Opt-out gives
those customers a clean answer for their third-party-risk register.
app.yaml gets a commented `CODA_TELEMETRY_DISABLED: "true"` example so
operators see the knob. 5 new unit tests cover truthy/falsy parsing and
that the background thread does NOT spawn when disabled.
E-11: Stable Flask secret_key via FLASK_SECRET_KEY (P2)
================================================================
app.py:56 used to be `app.secret_key = os.urandom(24)` — regenerated on
every worker restart, invalidating all Flask session cookies. With
single-worker config today this is mostly cosmetic (sessions get torn
down anyway when PTYs die with the worker), but it's a flagged finding
in any key-management audit and would actively break sessions if we
ever scaled to multi-worker.
Now reads FLASK_SECRET_KEY from env (typically wired to a Databricks
secret in app.yaml). Falls back to os.urandom for local dev with a
WARNING log line so operators see when production is using an ephemeral
key. app.yaml gets a commented example.
Test results
================================================================
- 244/244 unit tests pass
- 42/42 in the auth-enforcement + telemetry-opt-out + app-state suites
- Default behaviour unchanged when no new env vars are set
Out of scope (separate PRs / future work)
================================================================
- SBOM generation in the release workflow — PR #41
- Rate limiting on /api/configure-pat (E-3) — needs slowapi wire-up
- Session-level command audit trail (E-8) — medium effort, structured logs
- CSRF protection on /api/input (E-14) — medium effort
- `requests = git+https://...` PyPI proxy bypass (E-6) — blocked by
Databricks internal PyPI proxy availability
Co-authored-by: Isaac
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bundle of four enterprise-readiness improvements from an independent security review framed against NAB (APRA / CPS 234) and Coles Group (PCI-DSS / ISO 27001) procurement requirements. All four are low-risk and surgical; default behaviour is unchanged for non-enterprise deployments.
Together they close the document-review phase of any large-enterprise vendor security assessment. They do NOT close every finding from the review — the rest are tracked at the bottom of this PR description.
E-2 — Add
.github/SECURITY.md(P0 compliance blocker)Vendor security assessments (SIG / CAIQ) ask "do you have a documented vulnerability disclosure process?" The answer was no.
Now we have:
docs/enterprise.md§ known limits for the trade-offs already documentedE-4 — Remove
/api/app-statefrom auth-exempt list (P1)app.py:808had/api/app-statein the same exempt list as/health. Unauthenticated callers could fetchapp_owneremail +last_rotation_iso+owner_resolved_at— enough to fingerprint session timing and identify the workspace owner.The endpoint has no pre-auth use case (the polling endpoints the UI needs before PAT setup are
/api/setup-statusand/api/pat-status, both still exempt). Removed from the list, two regression tests added:test_app_state_denied_for_non_ownertest_app_state_allowed_for_ownerE-9 — Telemetry opt-out via
CODA_TELEMETRY_DISABLED(P2)log_telemetry()now short-circuits whenCODA_TELEMETRY_DISABLEDis truthy. Default behaviour unchanged (telemetry still on by default).Why this matters for procurement: regulated customers (banks, retailers with PCI-DSS) must inventory every outbound data flow from their workspace boundary. CoDA's User-Agent-header telemetry to Databricks servers was previously undisclosed and unsuppressible. Opt-out gives those customers a clean answer for their third-party-risk register.
app.yamlgets a commentedCODA_TELEMETRY_DISABLED: \"true\"example. 5 new unit tests cover truthy/falsy parsing and that the background thread doesn't spawn when disabled.E-11 — Stable Flask
secret_keyviaFLASK_SECRET_KEY(P2)app.py:56used to beapp.secret_key = os.urandom(24)— regenerated on every worker restart, invalidating Flask session cookies. With single-worker config today this is mostly cosmetic but it's a flagged finding in any key-management audit and would actively break sessions on multi-worker.Now reads
FLASK_SECRET_KEYfrom env (typically wired to a Databricks secret inapp.yaml). Falls back toos.urandomfor local dev with a WARNING log line so operators see when production is using an ephemeral key.Test plan
uv run pytest tests/— 244/244 passuv run pytest tests/test_auth_enforcement.py tests/test_telemetry_opt_out.py tests/test_app_state.py— 42/42 passcurl -i https://<app>/api/app-statefrom an unauth context now returns 403What's still open from the review
Tracked for follow-up PRs / triage, not in this bundle:
/api/configure-patslowapiwire-upcurl | bashClaude installer (no checksum)requests = git+https://...PyPI proxy bypassRotatingFileHandler/api/inputThis pull request and its description were written by Isaac.