Skip to content

Commit 041e11b

Browse files
committed
fix: redact sensitive headers in network request output
Network request details expose all HTTP headers in plain text, including sensitive values like Authorization tokens, Cookie values, and API keys. This data gets passed to the MCP client (typically an LLM) where it could be logged or inadvertently included in responses. Redact known sensitive headers (Authorization, Cookie, Set-Cookie, Proxy-Authorization) in both the text and structured JSON output of network request details.
1 parent 8d765c0 commit 041e11b

1 file changed

Lines changed: 30 additions & 3 deletions

File tree

src/formatters/NetworkFormatter.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ import type {HTTPRequest, HTTPResponse} from '../third_party/index.js';
1010

1111
const BODY_CONTEXT_SIZE_LIMIT = 10000;
1212

13+
const SENSITIVE_HEADERS = new Set([
14+
'authorization',
15+
'cookie',
16+
'set-cookie',
17+
'proxy-authorization',
18+
]);
19+
1320
export interface NetworkFormatterOptions {
1421
requestId?: number | string;
1522
selectedInDevToolsUI?: boolean;
@@ -204,10 +211,12 @@ export class NetworkFormatter {
204211

205212
return {
206213
...this.toJSON(),
207-
requestHeaders: this.#request.headers(),
214+
requestHeaders: NetworkFormatter.#redactHeaders(this.#request.headers()),
208215
requestBody: this.#requestBody,
209216
requestBodyFilePath: this.#requestBodyFilePath,
210-
responseHeaders: this.#request.response()?.headers(),
217+
responseHeaders: NetworkFormatter.#redactHeaders(
218+
this.#request.response()?.headers(),
219+
),
211220
responseBody: this.#responseBody,
212221
responseBodyFilePath: this.#responseBodyFilePath,
213222
failure: this.#request.failure()?.errorText,
@@ -217,6 +226,21 @@ export class NetworkFormatter {
217226
};
218227
}
219228

229+
static #redactHeaders(
230+
headers?: Record<string, string>,
231+
): Record<string, string> | undefined {
232+
if (!headers) {
233+
return undefined;
234+
}
235+
const redacted: Record<string, string> = {};
236+
for (const [name, value] of Object.entries(headers)) {
237+
redacted[name] = SENSITIVE_HEADERS.has(name.toLowerCase())
238+
? '<redacted>'
239+
: value;
240+
}
241+
return redacted;
242+
}
243+
220244
#getStatusFromRequest(request: HTTPRequest): string {
221245
const httpResponse = request.response();
222246
const failure = request.failure();
@@ -238,7 +262,10 @@ export class NetworkFormatter {
238262
#getFormattedHeaderValue(headers: Record<string, string>): string[] {
239263
const response: string[] = [];
240264
for (const [name, value] of Object.entries(headers)) {
241-
response.push(`- ${name}:${value}`);
265+
const displayValue = SENSITIVE_HEADERS.has(name.toLowerCase())
266+
? '<redacted>'
267+
: value;
268+
response.push(`- ${name}:${displayValue}`);
242269
}
243270
return response;
244271
}

0 commit comments

Comments
 (0)