Capturing Request Bodies for Forensics in Nuxt Without Leaking Secrets
Nuxt server middleware + h3 utilities give you a clean hook for body capture. Here's the redaction-aware pattern that works on Nuxt 3 and self-hosted Nitro.
Capturing Request Bodies for Forensics in Nuxt Without Leaking Secrets
Nuxt 3 server routes (in server/api/) get the body via readBody(event). Add a server middleware that runs before route handlers to capture it once.
The redaction utility
// server/utils/redact.ts
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',
]);
export function redact(obj: any, depth = 0): any {
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: any = {};
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;
}
The middleware
// server/middleware/forensics.ts
import { trace } from '@opentelemetry/api';
import { redact } from '../utils/redact';
export default defineEventHandler(async (event) => {
const path = getRequestURL(event).pathname;
if (!path.startsWith('/api/')) return;
// Read body — must use a non-destructive method since route handler will also call readBody
const body = await readBody(event).catch(() => null);
const headers = getHeaders(event);
const span = trace.getActiveSpan();
if (span) {
if (body) {
const safe = JSON.stringify(redact(body)).slice(0, 8192);
span.setAttribute('http.request.body', safe);
}
span.setAttribute('http.request.headers', JSON.stringify(redactHeaders(headers)));
}
});
function redactHeaders(headers: Record<string, string | undefined>) {
const result: Record<string, string> = {};
for (const [key, value] of Object.entries(headers)) {
if (!value) continue;
const lower = key.toLowerCase();
result[key] = (lower === 'authorization' || lower === 'cookie' || lower.startsWith('x-api-key'))
? '[REDACTED]'
: String(value);
}
return result;
}
Caveat: body consumption
readBody() consumes the request stream. If the middleware reads it, the route handler can't read it again. Two workarounds:
- Tee the body: read it in middleware, attach to event context, route handler reads from context.
event.context.cachedBody = await readBody(event);
In your route handler:
const body = event.context.cachedBody ?? await readBody(event);
- Use the SecureNow preload, which handles this transparently.
Response capture
// server/middleware/forensics-response.ts
export default defineEventHandler((event) => {
event.node.res.on('finish', () => {
// Capture response metadata only; body is harder to intercept
const span = trace.getActiveSpan();
span?.setAttribute('http.response.status', event.node.res.statusCode);
});
});
For full response body capture, use the SecureNow auto-instrumentation — manual response interception in Nitro is fiddly.
The automatic option
node -r securenow/register .output/server/index.mjs
Auto-captures bodies, headers, and response data with redaction across all Nuxt server routes. No middleware needed.
Related
Frequently Asked Questions
Does this work in Nuxt server routes (server/api)?
Yes. Capture happens in middleware that runs before the route handler, or inside the route handler using `readBody()`.
What about for Vercel-deployed Nuxt?
Same code works. The redaction logic doesn't depend on the runtime.
Is there an automatic option?
Yes — preload `securenow/register` and bodies are auto-captured with redaction across all Nuxt server routes.
Recommended reading
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 24A 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 24Part 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