Discovered during the 2026-05-26 dev re-deploy session.
What's happening
components/lif/mdr_utils/database_setup.py (or the equivalent caller) emits an INFO log line at MDR API startup that contains the full DATABASE_URL, including the Postgres password in plaintext:
2026-05-26 19:02:50,272 [INFO] lif.mdr_utils.database_setup:
DATABASE_URL : postgresql+asyncpg://postgres:<redacted-but-real-password>@devmdrdb.dev.aws:5432/devMdrDb
This is written to CloudWatch on every task start, in the shared dev log group (and presumably the equivalent on demo). Anyone with logs:FilterLogEvents on that group can recover the dev DB password by tailing the stream during startup.
Why this matters
- CloudWatch log retention defaults to "never expire" unless explicitly set, so each startup line is a long-lived plaintext credential
- The dev log group is shared across services and likely has broader-than-needed read permissions
- Demo (which is effectively prod for the 2026-05-27 client demo) almost certainly has the same code path
Pre-existing? Yes
This is not new in #884 — it's in MDR boot code that's been there since well before the self-serve feature work. We caught it because the new ECS deploy today caused a fresh startup and the log was visible. Linking under Self-Serve MDR: Security review / threat model for visibility, even though it's not strictly a #884 issue.
Fix sketch
In components/lif/mdr_utils/database_setup.py (or wherever DATABASE_URL is logged), redact the credential before logging:
from urllib.parse import urlparse, urlunparse
def _redact_url(url: str) -> str:
parts = urlparse(url)
if parts.password:
netloc = f"{parts.username}:***@{parts.hostname}"
if parts.port:
netloc += f":{parts.port}"
parts = parts._replace(netloc=netloc)
return urlunparse(parts)
logger.info("DATABASE_URL : %s", _redact_url(url))
Or omit the URL entirely from the log — the password isn't needed for operator debugging, only the host/db/user are.
Follow-up
- After the fix lands, rotate the dev + demo DB passwords (the current ones are in CloudWatch history)
- Audit other services in the repo (
graphql_*, translator_*, advisor_api, etc.) for similar log-leak patterns
Discovered during the 2026-05-26 dev re-deploy session.
What's happening
components/lif/mdr_utils/database_setup.py(or the equivalent caller) emits an INFO log line at MDR API startup that contains the fullDATABASE_URL, including the Postgres password in plaintext:This is written to CloudWatch on every task start, in the shared
devlog group (and presumably the equivalent on demo). Anyone withlogs:FilterLogEventson that group can recover the dev DB password by tailing the stream during startup.Why this matters
Pre-existing? Yes
This is not new in #884 — it's in MDR boot code that's been there since well before the self-serve feature work. We caught it because the new ECS deploy today caused a fresh startup and the log was visible. Linking under Self-Serve MDR: Security review / threat model for visibility, even though it's not strictly a #884 issue.
Fix sketch
In
components/lif/mdr_utils/database_setup.py(or whereverDATABASE_URLis logged), redact the credential before logging:Or omit the URL entirely from the log — the password isn't needed for operator debugging, only the host/db/user are.
Follow-up
graphql_*,translator_*,advisor_api, etc.) for similar log-leak patterns