No sensitive data in logs
Why it matters
CWE-532 (Insertion of Sensitive Information into Log File) is a direct path to credential theft: password hashes, session tokens, and API keys logged to stdout end up in your log aggregation platform, which typically has far weaker access controls than your primary database. PCI-DSS Req 10.3.3 explicitly prohibits logging cardholder data in any form; GDPR Art. 32 requires appropriate safeguards for personal data at rest and in transit — your log store is both. A single logger.info(req.body) in a payment handler can land card numbers, CVVs, and billing addresses in a third-party SaaS log platform, creating a compliance violation that persists for your entire log retention window. OWASP A09 lists sensitive data in logs as a primary logging failure mode.
Severity rationale
Critical because logged secrets, tokens, or PII remain exploitable for the full log retention period and may be exfiltrated from log infrastructure, which is rarely as hardened as your primary data store.
Remediation
Never log objects wholesale. Select only the fields you need, using explicit destructuring or field picks.
// WRONG — leaks everything in the user object including passwordHash
logger.info(user)
logger.debug(req.body)
// RIGHT — log only non-sensitive identifiers
logger.info({ userId: user.id }, 'User action')
logger.debug({ path: req.path, method: req.method }, 'Request received')
For Sentry, add a beforeSend scrubbing hook in your Sentry config file:
Sentry.init({
dsn: process.env.SENTRY_DSN,
beforeSend(event) {
if (event.request?.data) { delete event.request.data }
return event
}
})
After patching, run grep -r 'logger\.(info|debug|error)(user\|req\.body\|ctx)' app/ lib/ to confirm no wholesale object logging remains.
Detection
-
ID:
no-sensitive-data-logs -
Severity:
critical -
What to look for: Enumerate all relevant files and Search server-side code for logging calls that include potentially sensitive fields. Look for patterns where user objects, request bodies, or context objects are logged wholesale (e.g.,
logger.info(req.body),console.log(user),logger.debug({ ...ctx })). Specifically check for logging of: passwords, password hashes, tokens (JWT, API keys, session tokens), credit card numbers or payment details, full email addresses in debug output, SSNs, health data, or any field namedpassword,token,secret,key,ssn,credit_card,card_number,cvv. Also check Sentry/error reporter configuration for whether request data is sent unfiltered. -
Pass criteria: No more than 0 violations are acceptable. No logging calls that pass raw request bodies, user objects, or other data structures that could contain sensitive fields without explicit field-level selection. Sensitive fields are either excluded from log output or scrubbed. If an error reporter (Sentry, etc.) is configured, it either excludes request body by default or has a
beforeSend/denyUrls/ data-scrubbing configuration. Report the count of conforming instances found even on pass. -
Fail criteria: Any logging call found that passes a full user object, full request body, or any structure containing fields named password, token, secret, key, credit_card, ssn, or similar. OR an error reporter configured to send full request context without a scrubbing hook. A partial or incomplete implementation does not count as pass.
-
Skip (N/A) when: No server-side logging and no error reporting service configured.
-
Cross-reference: For API-level logging and monitoring patterns, the API Security audit covers request validation and error response handling.
-
Detail on fail: Describe specifically what was found and where. Do NOT include actual values from the code. Example:
"logger.debug(user) in src/lib/auth.ts logs full user object including passwordHash field"or"Sentry initialized in lib/monitoring.ts with no beforeSend scrubbing — full request body sent on error" -
Remediation: Logging sensitive data creates compliance violations (GDPR, HIPAA, PCI-DSS) and turns your log storage into an attack surface. A single breach of your logging infrastructure could expose all user credentials.
Never log objects wholesale. Always select specific fields:
// WRONG logger.info(user) logger.debug(req.body) // RIGHT logger.info({ userId: user.id, email: user.email }, 'User action') logger.debug({ path: req.path, method: req.method }, 'Request received')For Sentry, add a scrubbing hook:
Sentry.init({ dsn: process.env.SENTRY_DSN, beforeSend(event) { if (event.request?.data) { delete event.request.data // or selectively redact fields } return event } })After updating, search your codebase for any remaining
console.log(user),logger.info(req.body), or similar patterns.
External references
- cwe · CWE-532 — Insertion of Sensitive Information into Log File
- owasp:2021 · A09 — Security Logging and Monitoring Failures
- nist:rev5 · AU-3 — Content of Audit Records
- pci-dss:4.0 · Req 10.3.3 — Audit logs are protected from destruction and unauthorized modifications
- gdpr · Art. 32 — Security of processing
Taxons
History
- 2026-04-18·v1.0.0·Initial import from saas-logging·automated