Capturing Request Bodies for Forensics in Fastify Without Leaking Secrets

A Fastify preHandler hook captures bodies for forensics. Here's the redaction-aware version that won't put passwords in your logs.

May 9, 2026·4 min read

Capturing Request Bodies for Forensics in Fastify Without Leaking Secrets

Fastify's preHandler hook is the place. Bodies are parsed, route is matched, and you can attach the redacted version to your trace span before the handler runs.

The hook

import { trace } from '@opentelemetry/api';

const SENSITIVE = new Set([
  'password', 'pass', 'pwd', 'token', 'access_token', 'refresh_token',
  'api_key', 'apikey', 'secret', 'authorization', 'cookie', 'session',
  'creditcard', 'card_number', 'cvv', 'cvc', 'ssn',
]);

function redact(obj, depth = 0) {
  if (depth > 10) return '[max-depth]';
  if (obj == null || typeof obj !== 'object') return obj;
  if (Array.isArray(obj)) return obj.map(item => redact(item, depth + 1));

  const result = {};
  for (const [key, value] of Object.entries(obj)) {
    if (SENSITIVE.has(key.toLowerCase())) result[key] = '[REDACTED]';
    else if (typeof value === 'object') result[key] = redact(value, depth + 1);
    else result[key] = value;
  }
  return result;
}

export async function forensicsHook(req, reply) {
  const span = trace.getActiveSpan();
  if (!span) return;

  if (req.body && typeof req.body === 'object') {
    const safe = JSON.stringify(redact(req.body));
    span.setAttribute('http.request.body', safe.slice(0, 8192));
  }

  span.setAttribute('http.request.headers', JSON.stringify(redactHeaders(req.headers)));
}

function redactHeaders(headers) {
  const result = {};
  for (const [key, value] of Object.entries(headers)) {
    const lower = key.toLowerCase();
    result[key] = (lower === 'authorization' || lower === 'cookie' || lower.startsWith('x-api-key'))
      ? '[REDACTED]'
      : String(value);
  }
  return result;
}

Wiring globally

import Fastify from 'fastify';
import { forensicsHook } from './forensics.js';

const app = Fastify({ trustProxy: 1 });
app.addHook('preHandler', forensicsHook);

Multipart bodies

Skip file content; capture only field metadata:

async function safeMultipart(req) {
  if (!req.isMultipart?.()) return null;
  const fields = {};
  for await (const part of req.parts()) {
    if (part.type === 'field') {
      fields[part.fieldname] = SENSITIVE.has(part.fieldname.toLowerCase())
        ? '[REDACTED]'
        : part.value;
    } else {
      fields[part.fieldname] = `[file: ${part.filename}, ${part.mimetype}]`;
    }
  }
  return fields;
}

Response capture

app.addHook('onSend', async (req, reply, payload) => {
  const span = trace.getActiveSpan();
  if (span && payload && reply.getHeader('content-type')?.includes('json')) {
    try {
      const parsed = JSON.parse(payload);
      span.setAttribute('http.response.body', JSON.stringify(redact(parsed)).slice(0, 8192));
    } catch {}
  }
  return payload;
});

The automatic option

node -r securenow/register server.js

Auto-captures bodies, headers, response payloads with redaction across Fastify routes. The hand-rolled version above gives you fine control; SecureNow gives you maintenance-free.

Related

Frequently Asked Questions

Why preHandler instead of onRequest?

preHandler runs after body parsing, so `req.body` is populated. onRequest runs before parsing — no body to capture.

Does this work with all body types (JSON, multipart, etc.)?

JSON yes, multipart needs special handling because the file streams shouldn't be captured (huge). Multipart bodies should capture only the field metadata, not file contents.

Is there an automatic option?

Yes — preload `securenow/register` and the SDK auto-captures bodies for Fastify with redaction across all routes.

Recommended reading

AI Security Auditing, Part 1: Set Up Your AI Agent to Audit Your Code

Part 1 of the AI Security Auditing series. Set up an AI coding agent to audit your application's security locally — install SecureNow, connect your account, and run your first threat-model pass in minutes.

Jul 24
How to Audit Your App's Security With AI: The 2026 Guide

A practical, end-to-end guide to auditing your application's security with an AI coding agent — find vulnerabilities at the code level, build detections at the runtime level, and never upload your codebase to do it.

Jul 24
AI Security Auditing, Part 2: Audit Authentication & Sessions With AI

Part 2 of the AI Security Auditing series. Use an AI agent to audit your login, session, MFA, password-reset and magic-link flows for account-takeover paths — then catch the attempts in live traffic.

Jul 23