Node.js logging guide

How to redact secrets from Node.js logs

Sanitize a log record before serialization and transport, so API keys, credentials, authorization headers, and customer data never reach your log store.

By Umud Hasanli · Updated August 4, 2026 · Examples tested with Flare Redact 1.4

Short answer: redact at the logger boundary, before formatting or transport. Key-path rules protect fields you already know; content-aware scanning also catches a token pasted into message, note, an error, or another unexpected location.

Pino secret redaction

npm install flare-redact pino
import pino from 'pino';
import { pinoRedact } from 'flare-redact/pino';

const policy = {
  enable: ['high_entropy'],
  refineConfidence: true,
  minConfidence: 0.65
};

const log = pino(pinoRedact(policy));

log.info({
  email: 'alice@example.com',
  authorization: 'Bearer private-token-value'
}, 'checkout accepted');

The formatter receives a redacted copy. It checks sensitive field names and the contents of every string, so protection is not limited to a manually maintained list of object paths.

Winston secret redaction

npm install flare-redact winston
import winston from 'winston';
import { winstonRedact } from 'flare-redact/winston';

const safeFormat = winston.format(
  winstonRedact({ enable: ['high_entropy'] })
)();

const logger = winston.createLogger({
  format: winston.format.combine(safeFormat, winston.format.json()),
  transports: [new winston.transports.Console()]
});

Place the redaction transform before the JSON formatter and before every remote transport. Winston symbol metadata is preserved while ordinary record fields are sanitized.

Protect console output

For a small application or third-party code that writes to console.*, install a reversible wrapper during startup.

import { wrapConsole } from 'flare-redact';

const restoreConsole = wrapConsole();

console.error('request failed', {
  password: 'do-not-log-this',
  customer: 'alice@example.com'
});

// Call during teardown if the original console is needed.
restoreConsole();

Log an HTTP request without mutating it

Never destructively rewrite the live request just to make it safe for logging. Create a separate sanitized snapshot of its URL, query, params, headers, and body.

import { httpRedactor } from 'flare-redact/http';

app.use(httpRedactor(policy));

app.use((req, _res, next) => {
  log.info(req.redacted(), 'incoming request');
  next();
});

req remains unchanged for authentication and application logic. The value passed to the logger masks authorization and cookie headers as well as sensitive content elsewhere in the request.

Redact a log stream

If the boundary is a stream rather than a logger object, use the Node transform. It preserves enough trailing input to catch a secret split across chunks and handles bounded multiline private-key blocks.

import { redactStream } from 'flare-redact/stream';

process.stdin
  .pipe(redactStream(policy))
  .pipe(process.stdout);

Why redaction must happen before transport

A processor in your observability vendor is too late: the raw record has already crossed the process boundary and may exist in buffers, retries, ingestion logs, or another vendor system. The application should emit the safe representation first.