fix(security): harden session export image data-url handling

This commit is contained in:
Peter Steinberger
2026-02-24 02:52:33 +00:00
parent fefc414576
commit e578521ef4
8 changed files with 138 additions and 15 deletions

View File

@@ -107,4 +107,22 @@ describe("tool image sanitizing", () => {
const image = getImageBlock(out);
expect(image.mimeType).toBe("image/jpeg");
});
it("drops malformed image base64 payloads", async () => {
const blocks = [
{
type: "image" as const,
data: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO2N4j8AAAAASUVORK5CYII=" onerror="alert(1)',
mimeType: "image/png",
},
];
const out = await sanitizeContentBlocksImages(blocks, "test");
expect(out).toEqual([
{
type: "text",
text: "[test] omitted image payload: invalid base64",
},
]);
});
});

View File

@@ -1,6 +1,7 @@
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
import type { ImageContent } from "@mariozechner/pi-ai";
import { createSubsystemLogger } from "../logging/subsystem.js";
import { canonicalizeBase64 } from "../media/base64.js";
import {
buildImageResizeSideGrid,
getImageMetadata,
@@ -296,13 +297,21 @@ export async function sanitizeContentBlocksImages(
} satisfies TextContentBlock);
continue;
}
const canonicalData = canonicalizeBase64(data);
if (!canonicalData) {
out.push({
type: "text",
text: `[${label}] omitted image payload: invalid base64`,
} satisfies TextContentBlock);
continue;
}
try {
const inferredMimeType = inferMimeTypeFromBase64(data);
const inferredMimeType = inferMimeTypeFromBase64(canonicalData);
const mimeType = inferredMimeType ?? block.mimeType;
const fileName = inferImageFileName({ block, label, mediaPathHint });
const resized = await resizeImageBase64IfNeeded({
base64: data,
base64: canonicalData,
mimeType,
maxDimensionPx,
maxBytes,