Skip to main content

Overview

HTTP Ledger provides built-in security features to prevent sensitive data from appearing in logs. The primary security mechanism is field masking, which automatically replaces sensitive values with masked placeholders.

maskFields

maskFields
string[]
default:"[]"
Array of field names to mask in request bodies, response bodies, headers, and query parameters. Matching is case-insensitive.

Basic Usage

app.use(logger({
  maskFields: ['password', 'token', 'secret', 'apiKey']
}));

How Field Masking Works

When a field name matches an entry in maskFields, its value is replaced with "***MASKED***": Original Request:
{
  "username": "[email protected]",
  "password": "mySecretPassword123",
  "email": "[email protected]"
}
Logged Output:
{
  "username": "[email protected]",
  "password": "***MASKED***",
  "email": "[email protected]"
}

Nested Field Masking

Field masking works recursively on nested objects:
app.use(logger({
  maskFields: ['password', 'creditCard', 'ssn']
}));
Original Data:
{
  "user": {
    "name": "John Doe",
    "credentials": {
      "password": "secret123"
    }
  },
  "payment": {
    "creditCard": "4111-1111-1111-1111"
  }
}
Logged Output:
{
  "user": {
    "name": "John Doe",
    "credentials": {
      "password": "***MASKED***"
    }
  },
  "payment": {
    "creditCard": "***MASKED***"
  }
}

Common Sensitive Fields

Always mask authentication credentials, personal identifiable information (PII), and financial data.
app.use(logger({
  maskFields: [
    // Authentication
    'password',
    'passwd',
    'pwd',
    'token',
    'accessToken',
    'refreshToken',
    'apiKey',
    'api_key',
    'secret',
    'secretKey',
    'privateKey',
    
    // Financial
    'creditCard',
    'cardNumber',
    'cvv',
    'ssn',
    'bankAccount',
    
    // Personal
    'birthdate',
    'dob',
    'phone',
    'address'
  ]
}));

Masking in Different Contexts

Field masking applies to multiple parts of the request/response:

Request Bodies

app.use(logger({
  logBody: true,
  maskFields: ['password']
}));

// POST /api/login
// Body: { "email": "[email protected]", "password": "secret" }
// Logged: { "email": "[email protected]", "password": "***MASKED***" }

Response Bodies

app.use(logger({
  logResponse: true,
  maskFields: ['accessToken', 'refreshToken']
}));

// Response: { "user": {...}, "accessToken": "eyJhbG...", "refreshToken": "def50200..." }
// Logged: { "user": {...}, "accessToken": "***MASKED***", "refreshToken": "***MASKED***" }

Query Parameters

app.use(logger({
  logQueryParams: true,
  maskFields: ['api_key', 'token']
}));

// GET /api/data?api_key=secret123&user=john
// Logged queryParams: { "api_key": "***MASKED***", "user": "john" }

Headers

app.use(logger({
  maskFields: ['authorization'],
  excludedHeaders: [] // Don't exclude, just mask
}));

// Headers: { "authorization": "Bearer token123", "content-type": "application/json" }
// Logged: { "authorization": "***MASKED***", "content-type": "application/json" }

Combining with Header Exclusion

You can combine maskFields with excludedHeaders for defense in depth:
app.use(logger({
  // Completely remove these headers from logs
  excludedHeaders: ['authorization', 'cookie'],
  
  // Mask these fields in bodies and query params
  maskFields: ['password', 'token', 'secret']
}));
Use excludedHeaders when you don’t want the header logged at all. Use maskFields when you want to know the field was present but hide its value.

Production Security Example

Here’s a comprehensive security configuration for production:
const express = require('express');
const logger = require('http-ledger');

const app = express();

app.use(logger({
  // Exclude authentication headers entirely
  excludedHeaders: [
    'authorization',
    'cookie',
    'x-api-key',
    'x-auth-token'
  ],
  
  // Mask sensitive fields in bodies and query params
  maskFields: [
    'password',
    'passwd',
    'token',
    'accessToken',
    'refreshToken',
    'apiKey',
    'api_key',
    'secret',
    'secretKey',
    'creditCard',
    'cardNumber',
    'cvv',
    'ssn'
  ],
  
  // Don't log bodies in production to reduce exposure
  logBody: process.env.NODE_ENV === 'development',
  logResponse: false
}));

Security Best Practices

Always Mask Credentials

Never log passwords, API keys, tokens, or authentication credentials in plain text

Protect PII

Mask personal identifiable information like SSN, credit cards, addresses

Environment-Based Logging

Disable body logging in production to minimize sensitive data exposure

Regular Audits

Regularly review logs to ensure no sensitive data is leaking

Implementation Details

Field masking is implemented in src/utils/logFormatter.ts:76-98. The masking:
  • Works recursively on nested objects
  • Is case-insensitive
  • Applies to arrays of objects
  • Replaces any data type with "***MASKED***"
  • Occurs before custom formatters run
Field masking happens in-memory and doesn’t modify the original request/response objects. It only affects the logged output.

Basic Options

Control what gets logged with logBody and excludedHeaders

Production Setup

Complete production security configuration guide

Build docs developers (and LLMs) love