You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
CORS configured and restrictable via CORS_ORIGINS setting
Verified
Default is http://localhost:5173 (local dev), not *; list explicit origins in production. allow_credentials=True, so never set CORS_ORIGINS=* — the app now refuses to boot if CORS_ORIGINS contains * (M3, validated at startup)
39
WWW-Authenticate headers sent on 401 responses
Verified
Bearer and Basic auth return appropriate challenge headers
40
Request correlation IDs present in all structured logs
Verified
RequestLoggingMiddleware attaches request_id
Scheduler Security
#
Check
Status
Notes
41
Scheduled jobs use stored connection credentials (not request-time)
Verified
Job execution reads from encrypted DB records
42
Job execution errors logged but not exposed to data API consumers
Verified
Job run records stored internally; data endpoint returns 503
43
Job concurrency limited to prevent resource exhaustion
Verified
max_instances=1 per job, max_job_concurrency setting
Every dynamic data endpoint requires authentication
Verified
A configured endpoint method is enforced when present. Otherwise the legacy allow_unauthenticated=true value opts into platform-admin Bearer fallback; it never permits anonymous access. Missing or invalid credentials return 401 and log unauthenticated_endpoint_denied.
52
App refuses to boot with wildcard CORS under credentials
Verified
M3: cors_origins validator rejects * at startup
53
API keys accepted only via header, not query string
Scheduled queries never inherit endpoint request defaults
Verified
Schedule creation requires exactly one validated binding per SQL parameter; execution resolves only parameter_bindings_json
67
Every parameterized snapshot request has an allowlisted cached-column mapping
Verified
Endpoint create/update requires a post-rename column plus eq, gte, or lte for every parameter
68
Cached data is served only after retained-run coverage and typed row filtering
Verified
DataService._serve_snapshot() selects the newest covering job run, validates mapped columns, and calls filter_snapshot_rows(); no unfiltered fallback exists
69
Range and SQL NULL coverage semantics fail closed
Verified
Reversed bounds return 422; range types must match; null_means_all is limited to optional equality mappings
70
Snapshot filter mappings cannot substitute for authorization
Verified
Data authentication runs before snapshot selection; store_id and other mapped values are ordinary row filters only
71
SQL bind discovery has linear processing cost
Verified
A monotonic scanner masks quoted/commented regions before bind extraction; adversarial unterminated Q-quote input is regression-tested
Summary
Verified items: 65/71
Action required: 6/71
High-severity unresolved findings: 0
All code-level security controls validated through automated tests
The 6 "Action Required" items are environment/repo-admin configurations that
must be applied per installation: the original deployment-config items
(DEBUG=false, ENCRYPTION_KEY in a secrets manager, HTTPS termination,
PostgreSQL network isolation — see the Deployment Runbook)
plus branch protection and image signing (#63–#64 — see
repository_governance.md).