Skip to main content

Client Logging and Telemetry Sanitization

This document describes how RECORD-3297 protects client-side logs and telemetry from leaking sensitive data.

Scope

Sanitization applies to runtime logging and telemetry paths in the web app:

  • Shared logger dispatch in src/utils/logger.ts
  • Log payload sanitization policy in src/utils/logSanitization.ts
  • New Relic telemetry/error recording in src/providers/instrumentation/newrelic/instrumentation.ts
  • Error boundary logging in src/app/error.tsx and src/app/global-error.tsx
  • Network failure diagnostics in src/utils/fetcher.ts

Redaction Policy

The sanitization policy is centralized in src/utils/logSanitization.ts and is shared by logger and telemetry layers.

Sensitive keys

Objects are key-sanitized when field names indicate potentially sensitive content. Coverage includes tokens and auth fields, account/session identifiers, payment fields, and PII-oriented keys. Examples:

  • token-like: token, accessToken, refreshToken, authorization, apiKey, cookie
  • auth/secret-like: password, pin, secret, bearer, jwt
  • session/device-like: session, sessionId, session_id, deviceId, device_id
  • payment-like: cvv, cvc, card, cardNumber, iban, billing
  • PII-like: email, phone, firstName, lastName, fullName, username, address

Sensitive string patterns

String content is sanitized with pattern redaction:

  • Bearer credentials: Bearer [REDACTED]
  • JWT-like tokens: [REDACTED_JWT]
  • Email addresses: [REDACTED_EMAIL]
  • Phone numbers: [REDACTED_PHONE]
  • Card numbers (Luhn-valid): [REDACTED_CARD]
  • URL query/hash removal: query and fragment are removed from URL-like values
  • Inline key-value fragments: session_id=..., device_id=..., authorization=..., cvv=... are redacted to [REDACTED]

Type behavior

  • primitives: strings sanitized, numbers/booleans preserved
  • URL values: reduced to safe path-only form for relative URLs, query/hash stripped for absolute URLs
  • Error objects: name/message/stack/cause sanitized recursively
  • arrays and nested objects: recursively sanitized
  • circular references: replaced with [Circular]
  • deep recursion guard: replaced with [Truncated] beyond max depth

Logging Strategy

Shared logger

All runtime logger calls sanitize arguments before provider dispatch. This means all logger methods (debug/info/log/warn/error) route through the same sanitization boundary.

Console bypass handling

Runtime direct console usage in targeted app paths has been replaced by shared logger usage, so sanitization cannot be bypassed by normal runtime code paths.

Telemetry Strategy

New Relic calls sanitize event names, custom attributes, and error details before emission:

  • recordEvent uses sanitized names and attributes
  • recordError sanitizes context attributes and error details
  • noticeError receives sanitized error strings

Additionally, high-risk telemetry attributes have been reduced to safe metadata in relevant call paths (for example booleans instead of raw media URLs).

Network and Error Boundary Behavior

Fetcher diagnostics

Network failure logging uses safe metadata rather than raw URLs/payloads:

  • endpointPath (pathname only)
  • status
  • statusText

No raw request/response headers, cookies, or body payload dumps are intentionally emitted in fetcher diagnostics.

Error boundaries

Error boundary and global error boundary logging now rely on sanitized logger payload behavior and avoid unsafe raw field leakage.

Sanitized Evidence Samples

Representative outputs after sanitization:

{
accessToken: "abc",
profile: { email: "user@example.com", phone: "+1 202-555-0179" }
}
  • Output object:
{
accessToken: "[REDACTED]",
profile: { email: "[REDACTED]", phone: "[REDACTED]" }
}

Validation Evidence

Focused test evidence command:

pnpm test:once src/utils/tests/logSanitization.test.ts src/app/tests/error.test.tsx src/app/tests/global-error.test.tsx src/providers/instrumentation/newrelic/tests/instrumentation.test.ts --no-coverage

Result:

  • 4/4 suites passed
  • 27/27 tests passed

Acceptance Criteria Checklist

  • AC: No credentials/tokens/session IDs/device IDs exposed in client logs

    • Covered by inline/string/object sanitization tests in src/utils/tests/logSanitization.test.ts
  • AC: PII and payment-related values are redacted in logs and telemetry

    • Covered by policy tests and telemetry tests in src/providers/instrumentation/newrelic/tests/instrumentation.test.ts
  • AC: Error reporting preserves diagnostics without leaking sensitive payloads

    • Covered by sanitized error processing in src/providers/instrumentation/newrelic/instrumentation.ts and boundary tests in src/app/tests/error.test.tsx and src/app/tests/global-error.test.tsx
  • AC: Runtime logging does not bypass sanitization strategy

    • Covered by migration to shared logger in targeted runtime modules and logger sanitization behavior in src/utils/logger.ts
  • AC: Production logging is non-verbose and safer by default

    • Covered by production log-level floor in src/utils/logger.ts and src/utils/logSanitization.ts
  • AC: Network diagnostics avoid raw response/request sensitive payload emission

    • Covered by safe endpoint/status logging behavior in src/utils/fetcher.ts

Notes

  • redactString in src/utils/string.ts remains available for non-security partial masking use cases.
  • Security-sensitive logging and telemetry paths must use src/utils/logSanitization.ts policy behavior as the canonical approach.