PII excluded from application logs
Why it matters
CWE-532 (insertion of sensitive information into log files) directly applies when account numbers, SSNs, or email addresses appear in application logs. Financial application logs are typically stored in cloud logging services (CloudWatch, Datadog, Splunk) with broader access than the production database — developers, support staff, and contractors may all have log read access without needing database access. PCI-DSS 4.0 Req-3.3 explicitly prohibits storing sensitive authentication data after authorization. OWASP 2021 A09 (Security Logging and Monitoring Failures) includes inadequate log sanitization. A single console.log(transaction) that dumps the full transaction object will log account numbers in plaintext to every log aggregator in the pipeline.
Severity rationale
Low severity at this check level because PII in logs requires log access to exploit, but the compliance impact is equivalent to a data exposure event under PCI-DSS and most state breach notification laws.
Remediation
Create masking utilities in src/lib/logging.ts and use them consistently in all transaction-path logging:
// src/lib/logging.ts
export const mask = {
accountNumber: (v: string) => `****${v.slice(-4)}`,
ssn: (v: string) => `***-**-${v.slice(-4)}`,
email: (v: string) => {
const [local, domain] = v.split('@');
return `${local[0]}***@${domain}`;
},
cardToken: (v: string) => `tok_****${v.slice(-4)}`,
};
// Usage:
logger.info('transfer_initiated', {
account: mask.accountNumber(accountNumber),
amount: transferAmount, // numeric, safe to log
currency: 'USD',
});
Add a pre-commit lint rule or custom ESLint plugin that flags console.log or logger.* calls in src/app/api/ routes that reference known PII field names (ssn, accountNumber, cardToken, email). Review all existing logs for historical PII exposure and rotate credentials if any appear.
Detection
- ID:
pii-excluded-from-logs - Severity:
low - What to look for: Count all logging statements in financial transaction code paths. For each, enumerate the data fields logged and classify as PII or non-PII. Quote the actual field names logged. Count all PII masking/redaction functions. Any unmasked PII in logging must not pass — do not pass if any logging statement outputs full account numbers, SSNs, or email addresses.
- Pass criteria: Count all logging statements — 0 must log unmasked PII. At least 1 masking/redaction utility exists if PII fields are referenced in logs. Report the count even on pass (e.g., "12 logging statements checked, 0 unmasked PII, 2 masking functions: maskAccountNumber(), maskSSN()").
- Fail criteria: Any PII logged unmasked (even 1 instance of full account number, SSN, or email in logs).
- Skip (N/A) when: Never — logging PII is a compliance violation for any financial system.
- Detail on fail:
"3 of 12 logging statements log unmasked PII — full account_number in src/services/transfer.ts:45"or"Customer SSN logged unmasked in debug output at src/app/api/account/route.ts:23" - Cross-reference: Check
finserv-encryption.data-at-rest.aes256-encryptionfor data encryption, andfinserv-encryption.pci-alignment.encryption-documentationfor compliance documentation. - Remediation:
- Create PII masking utilities:
const maskAccountNumber = (account: string) => { return account.slice(-4).padStart(account.length, '*'); }; const maskSSN = (ssn: string) => { return ssn.slice(-4).padStart(ssn.length, '*'); }; logger.info('Transaction', { account: maskAccountNumber(accountNumber), amount: 100, }); - Review and redact existing logs:
// Log filter to remove PII const redactLogs = (logEntry: any) => { const redactedEntry = { ...logEntry }; if (redactedEntry.ssn) delete redactedEntry.ssn; if (redactedEntry.accountNumber) redactedEntry.accountNumber = maskAccountNumber(redactedEntry.accountNumber); return redactedEntry; };
- Create PII masking utilities:
External references
- cwe · CWE-532 — Insertion of Sensitive Information into Log File
- owasp:2021 · A09 — Security Logging and Monitoring Failures
- pci-dss:4.0 · Req-3.3 — Sensitive authentication data not stored after authorization
- nist:rev5 · SI-12 — Information Management and Retention
Taxons
History
- 2026-04-18·v1.0.0·Initial import from finserv-encryption·automated