diff --git a/packages/coding-agent/src/core/export-html/template.js b/packages/coding-agent/src/core/export-html/template.js
index 3f4c40f6..27dff747 100644
--- a/packages/coding-agent/src/core/export-html/template.js
+++ b/packages/coding-agent/src/core/export-html/template.js
@@ -881,7 +881,7 @@
const images = getResultImages();
if (images.length === 0) return '';
return '
';
};
@@ -1148,7 +1148,7 @@
if (images.length > 0) {
html += '';
for (const img of images) {
- html += `
};base64,${img.data})
`;
+ html += `
};base64,${escapeHtml(img.data || '')})
`;
}
html += '
';
}
diff --git a/packages/coding-agent/test/export-html-xss.test.ts b/packages/coding-agent/test/export-html-xss.test.ts
index 077a0d12..88f4298e 100644
--- a/packages/coding-agent/test/export-html-xss.test.ts
+++ b/packages/coding-agent/test/export-html-xss.test.ts
@@ -25,4 +25,10 @@ describe("export HTML markdown link sanitization", () => {
expect(templateJs).not.toMatch(/\$\{img\.mimeType\}/);
expect(templateJs).toMatch(/escapeHtml\(img\.mimeType/);
});
+
+ it("escapes image data attributes", () => {
+ // Image data is embedded in src attributes and must not allow attribute breakout.
+ expect(templateJs).not.toMatch(/;base64,\$\{img\.data\}"/);
+ expect(templateJs).toMatch(/;base64,\$\{escapeHtml\(img\.data \|\| (?:''|"")\)\}"/);
+ });
});