From 57787b6557b9129189e0fe03bf47f9779938ed63 Mon Sep 17 00:00:00 2001 From: Justin Barnett Date: Tue, 28 Apr 2026 05:46:42 -0400 Subject: [PATCH] fix(coding-agent): escape exported session metadata (#3883) --- .../src/core/export-html/template.js | 30 +++++++++---------- .../coding-agent/test/export-html-xss.test.ts | 28 +++++++++++++++++ 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/packages/coding-agent/src/core/export-html/template.js b/packages/coding-agent/src/core/export-html/template.js index 27dff747..844f1eb3 100644 --- a/packages/coding-agent/src/core/export-html/template.js +++ b/packages/coding-agent/src/core/export-html/template.js @@ -634,13 +634,13 @@ if (toolCall) { return labelHtml + `${escapeHtml(formatToolCall(toolCall.name, toolCall.arguments))}`; } - return labelHtml + `[${msg.toolName || 'tool'}]`; + return labelHtml + `[${escapeHtml(msg.toolName || 'tool')}]`; } if (msg.role === 'bashExecution') { const cmd = truncate(normalize(msg.command || '')); return labelHtml + `[bash]: ${escapeHtml(cmd)}`; } - return labelHtml + `[${msg.role}]`; + return labelHtml + `[${escapeHtml(msg.role)}]`; } case 'compaction': return labelHtml + `[compaction: ${Math.round(entry.tokensBefore/1000)}k tokens]`; @@ -653,11 +653,11 @@ return labelHtml + `[${escapeHtml(entry.customType)}]: ${escapeHtml(truncate(normalize(content)))}`; } case 'model_change': - return labelHtml + `[model: ${entry.modelId}]`; + return labelHtml + `[model: ${escapeHtml(entry.modelId)}]`; case 'thinking_level_change': - return labelHtml + `[thinking: ${entry.thinkingLevel}]`; + return labelHtml + `[thinking: ${escapeHtml(entry.thinkingLevel)}]`; default: - return labelHtml + `[${entry.type}]`; + return labelHtml + `[${escapeHtml(entry.type)}]`; } } @@ -1122,7 +1122,7 @@ * Render the copy-link button HTML for a message. */ function renderCopyLinkButton(entryId) { - return `