fix(canvas): escape data.json before inlining it into the exported <script> - #17
Open
245678000000 wants to merge 1 commit into
Open
Conversation
…cript>
buildSingleFileHtml interpolated the canvas data.json straight into an
inline <script> block:
data: new Map(Object.entries(${dataJson || '{}'})),
An HTML parser ends a script block at the first `</script`, regardless of
whether it sits inside a JS string literal. data.json is user/model
content (it arrives as DashboardService.ShareCanvas's data_json), so any
string value containing `</script>` truncates the exported file and the
remainder is parsed as DOM. The sibling `title` was already run through
escapeHtml; this path was missed.
Escape `<` as the JSON escape U+003C before interpolating. In JSON `<`
can only occur inside a string literal, so the escape is semantically
identical and the data still parses back to the same value.
Adds canvasExport.test.ts: round-trip, no new `</script` from a hostile
payload, and value preservation. Two of the three fail without the fix.
Rogers-F
added a commit
to Rogers-F/CCursor
that referenced
this pull request
Aug 29, 2026
- buildSummarySource: 总预算 min(0.6×窗口×4, 3.2e6) chars, 超限走官方
CC-012 max-min 水位分配 (长度升序配额; <200 chars 整条丢弃打
[omitted {role} message, N chars] 占位; user 截断保 <user_query> 块;
Read/Task 截断强制保留路径清单 + error/fail 行 + 末段结论)
- 三级兜底 streamSummaryWithFallback / generateSummaryWithFallback:
≤3 次重试 (attempt≥2 附 "Write a shorter summary" + 源预算递减
max(50K, min(÷2/÷3, 0.75×原长)); attempt 3 剥控制字符) → 确定性降级
(不经模型, 水位拼接 + 注入防御声明, 预算 clamp(窗口×2%×4, 50K, 3.2M))
→ '- Prior conversation compacted.'; 两路 runtime 换用同一实现
(流式 delta + heartbeat 保活)
- SUMMARY_HARD_CAP = 2×summaryReserve: 产出超限 → 一次 shorter-output
重试 → 仍超则 token 级裁剪至 cap, 超支率进观测日志
- SUMMARY_USER_TEMPLATE 附加 [truncated]/[omitted] 工具输出段
(SYSTEM_PROMPT 不动): 摘要须保留路径/命令/agentId 与结论,
原文可重跑工具找回
- 测试: CometixSpace#11 摘要源封顶+路径错误行 / CometixSpace#16 三次失败→确定性降级含防御声明 /
CometixSpace#17 水位分配 200 条不等长+user_query 存续 / #33 输出硬上界裁剪
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
buildSingleFileHtmlinCursor++/src/server/handlers/canvas/canvasStore.tsinterpolates the canvasdata.jsonstraight into an inline<script>block:An HTML parser ends a script block at the first
</script, regardless of whether it sits inside a JS string literal.data.jsonis user/model content — it arrives asDashboardService.ShareCanvas'sdata_json(services/account/DashboardService.ts:115) — so any string value containing</script>truncates the exported file and everything after it is parsed as DOM.The sibling
titlein the same template already goes throughescapeHtml; this path was missed.Repro
Fix
Escape
<as the JSON escape\u003cbefore interpolating, via a small helper next toescapeHtml. In JSON<can only occur inside a string literal, so the escape is semantically identical — the data still parses back to exactly the same value.bundleBase64needs no change (base64 has no<), andbuildIndexHtmldoesn't interpolate data at all.Test plan
New
Cursor++/src/server/tests/canvasExport.test.ts— round-trip of ordinary data, no new</scriptfrom a hostile payload, and value preservation after escaping. Two of the three fail without the source change (verified by stashing the fix).pnpm --dir "Cursor++" run check-typespnpm --dir "Cursor++" run lintpnpm --dir "Cursor++" run test:server— 39 files / 370 tests passed (baseline onmainis 38 / 367)