Files
rea/src/browser/history/HarCaptureProcess.ts
T
93ca276921 fix(browser): accept HAR files that begin with a byte-order mark (#1509)
HAR 1.2 lets writers emit a UTF-8 byte-order mark and requires readers to
ignore it. The decoder passed ignoreBOM: true to TextDecoder, which keeps
the mark in the decoded text, so a BOM-prefixed export failed as "HAR is
malformed JSON." Decoding now uses the default, which skips one leading
mark. The artifact digest still covers the selected file bytes.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:31:31 -07:00

59 lines
1.9 KiB
TypeScript

import { readFile, writeFile } from "node:fs/promises";
import { z } from "zod";
import { readStableArtifact } from "../../artifacts/readStableArtifact.js";
import { WEB_NETWORK_CAPTURE_LIMITS } from "../../domain/webNetworkCapture.js";
import { CaptureFormatError } from "./CaptureFormatError.js";
import { decodeHarCapture, decodeHarText } from "./HarCapture.js";
const requestSchema = z.strictObject({
snapshot_path: z.string(),
reply_path: z.string(),
sensitive_values: z.array(z.string().min(1)),
});
/** Decode untrusted HAR in an owned, bounded heap rather than the long-lived MCP process. */
const main = async (): Promise<void> => {
const request = requestSchema.parse(
JSON.parse(await readFile(process.argv[2] ?? "", "utf8")),
);
let reply: unknown;
try {
const snapshot = await readStableArtifact(
request.snapshot_path,
WEB_NETWORK_CAPTURE_LIMITS.inputBytes,
);
reply = {
ok: true,
value: decodeHarCapture(
decodeHarText(snapshot.bytes),
request.sensitive_values,
),
};
} catch (cause: unknown) {
reply =
cause instanceof CaptureFormatError
? {
ok: false,
reason: cause.reason,
message: cause.message,
pointer: cause.pointer,
}
: {
ok: false,
reason: "decoder",
message: `HAR decoder failed unexpectedly (${cause instanceof Error ? cause.name : "unknown exception"}).`,
pointer: "",
};
}
let text = JSON.stringify(reply);
if (Buffer.byteLength(text) > WEB_NETWORK_CAPTURE_LIMITS.outputBytes)
text = JSON.stringify({
ok: false,
reason: "limit",
message: "HAR reply exceeds the complete-evidence output budget.",
pointer: "",
});
await writeFile(request.reply_path, text, { flag: "wx", mode: 0o600 });
};
await main();