No PII, card data, or session tokens in server logs
Why it matters
Server-side console.log(req.body), logger.info({ user, session }), or Sentry.captureException(err, { extra: { headers } }) calls that dump full request bodies, card numbers, CVVs, session tokens, or API keys have two compounding cost consequences beyond privacy exposure. First, PCI scope expansion — the moment a credit-card field lands in a log line, the log ingestion pipeline (Datadog, CloudWatch, Loki, Sentry, Logtail) becomes "in-scope" for PCI-DSS audits, adding roughly $50K-$200K per year in compliance overhead for QSA assessments, retention encryption, and access-control review. Second, abuse-replay blast radius — anyone with log read access (your ops team, Sentry seat-holders, a compromised vendor) can replay sessions, hijack tokens, or reuse cards. The 2022 Twilio incident exposed years of customer PII because log infrastructure was compromised; Capital One's 2019 IAM-misconfigured S3 logs resulted in 100M records leaked. PCI-DSS Req 3.2 explicitly prohibits storing authentication data post-authorization in any unprotected location, including logs. AI scaffolding produces this pattern casually: "add logging" becomes console.log(req.body) without a redactor in the loop.
Severity rationale
High because one tainted log pipeline can expand PCI scope by hundreds of thousands of dollars per year and any log reader effectively becomes an auth principal.
Remediation
Strip sensitive fields before logging: introduce a redact(obj) helper that drops password, token, apiKey, cardNumber, cvv, authorization, cookie, session, and full req.body / req.headers objects, and route every console.log or logger.* call through it. For Sentry, configure beforeSend to scrub the same fields. Log scope markers ([auth-flow] step 2 userId=abc123) instead of full objects.
Deeper remediation guidance and cross-reference coverage for this check lives in the security-hardening and saas-logging Pro audits — run those after applying this fix for a more exhaustive pass on the same topic.
Detection
- ID:
no-pii-in-server-logs - Severity:
high - What to look for: Grep server-side code directories (
app/api/**,pages/api/**, server components,lib/**,server/**, middleware files) forconsole.log,console.error,console.warn,console.debug,logger.info,logger.debug,logger.error,logger.warn, andSentry.captureException(..., { extra: ... })calls whose argument list includes any of:req.body,req.headers,cookies(),headers(),user(full object),session,email,password,pinHash,token,apiKey,api_key,cardNumber,card_number,cvv,expiryDate,ssn,phone,address,firstName,lastName. Also flag whole-request dumps:console.log(req),console.log(JSON.stringify(req.body)),logger.info(event)whereeventis the raw handler input. Scope markers likeconsole.log('[auth-flow] step 2')orlogger.info({ userId })(opaque id only, no PII) are fine. - Pass criteria: Zero server-side log or Sentry calls dumping PII, credit-card fields, session tokens, or full request bodies/headers.
- Fail criteria: One or more server-side log or Sentry calls dumping any of the listed sensitive fields. Detail must name the file and the log call type.
- Skip (N/A) when: No server-side code exists (project is a pure static SPA, CLI tool with no network handlers, or library with no runtime request-handling). Report the absence of
app/api,pages/api, andserver/directories as evidence. - Do NOT pass when: A log call dumps
req.body"for debugging" — it still ships to production log infrastructure. - Before evaluating, quote: Quote the file path and the log line for every match. If zero matches, report
"0 sensitive-log matches across N server-side files scanned". - Report even on pass: Report the count of server-side files scanned and the count of matches:
"Scanned ~X server-side files, 0 sensitive-field log patterns matched". - Detail on fail:
"Full request body logged in app/api/auth/login/route.ts — console.log(req.body) includes password field"— name the file, the log call, and the specific sensitive field being dumped. - Remediation: Strip sensitive fields before logging: introduce a
redact(obj)helper that dropspassword,token,apiKey,cardNumber,cvv,authorization,cookie,session, and fullreq.body/req.headersobjects, and route everyconsole.logorlogger.*call through it. For Sentry, configurebeforeSendto scrub the same fields. Log scope markers ([auth-flow] step 2 userId=abc123) instead of full objects.
External references
- cwe:4.14 · CWE-532 — Insertion of Sensitive Information into Log File
- pci-dss:4.0 · Req 3.2 — Do not store sensitive authentication data after authorization
Taxons
History
- 2026-04-23·v1.0.0·Initial authoring for Stack Scan v3.1 abuse bucket (twin of legal/no-pii-in-server-logs)·by phase-9-1-stack-scan-v3-1