Root cause
Injection & unsafe execution introduced
The export command loads the installed HTML template script used to render session content.
How AI contributed: Direct introductionPublished Feb 24, 2026 in
openclaw/openclawAll 35 findings in this repository
Provisional finding. Full causal and release verification remains incomplete.
Root cause
The export command loads the installed HTML template script used to render session content.
Fix
The image renderer accepts only MIME values matching the safe image-type pattern.
Case facts
@@ -0,0 +69,18 @@+ return fs.readFileSync(path.join(getExportDir(), fileName), "utf-8");+}++function generateHtml(sessionData: SessionData): string {+ const template = loadTemplate("template.html");+ const templateCss = loadTemplate("template.css");+ const templateJs = loadTemplate("template.js");+ const markedJs = loadTemplate(path.join("vendor", "marked.min.js"));+ const hljsJs = loadTemplate(path.join("vendor", "highlight.min.js"));++ // Use default theme colors+ const themeVars = `+ --bg: #1a1a2e;+ --fg: #eaeaea;+ --userMessageBg: #2d2d44;+ --assistantMessageBg: #1e1e30;+ --toolCallBg: #252538;+ --toolResultBg: #1c1c2c;@@ -664,9 +664,18 @@ div.textContent = text; return div.innerHTML; } + // Validate image MIME type to prevent attribute injection in data-URL src.+ const SAFE_IMAGE_MIME_RE = /^image\/(png|jpeg|gif|webp|svg\+xml|bmp|tiff|avif)$/i;+ function sanitizeImageMimeType(mimeType) {+ if (typeof mimeType === "string" && SAFE_IMAGE_MIME_RE.test(mimeType)) {+ return mimeType;+ }+ return "application/octet-stream";+ }+ /** * Truncate string to maxLen chars, append "..." if truncated. */ function truncate(s, maxLen = 100) { if (s.length <= maxLen) {AI-assisted change 97cf02ec0674d2cf70a9a85825f07c59fcc9e94b1b28bd57751ac25521472e45 · Fix f34b02c5711f32b3927e9bc17aed5ee5cb8e2ff3efbfac9cd50b74e018ba0459