Repository navigation
fix(vscode): sanitize chat webview markdown and block remote images - #1927
Open
Mahdi-Hasan wants to merge 1 commit into
Open
Mahdi-Hasan wants to merge 1 commit into
Mahdi-Hasan wants to merge 1 commit into
Conversation
Mahdi-Hasan
requested review from
addyCooks,
akramcodez and
will-lamerton
as code owners
November 2, 2026 12:19
Contributor
|
nc-review could not produce a verdict this run (agent exit |
Mahdi-Hasan
force-pushed
the
fix/1727-sanitize-webview-markdown
branch
from
November 2, 2026 12:24
d0be1a3 to
3a4c462
Compare
The chat panel put marked.parse() output for replies, thoughts and replayed user messages straight into innerHTML. Raw HTML in a reply could add <style> rules, inline styles or the panel's own Tailwind classes and restyle or cover the webview. The CSP also allowed any https: image, so a reply could make the editor fetch a tracking pixel. All five marked sinks now go through setMarkdown(), which renders via the new media/markdown-utils.js. It runs marked output through a vendored DOMPurify 3.4.17 build (media/purify.min.js, loaded the same way as marked.min.js) with the HTML profile only, no <style>, style="", or <form>, prefixed ids, and no class other than a code block's language-*. If DOMPurify is missing or reports no DOM support, the panel shows the text instead of unsanitized HTML. img-src drops https:. Uploaded and pasted images are data: URIs and nothing else in the panel loads remote images. markdown-utils.spec.ts runs the shipped marked, DOMPurify and helper in jsdom (new devDependency of the extension) and checks the policy and the CSP. chat-panel-markdown.spec.ts drives the panel harness to check every sink is sanitized and that it fails closed. Fixes Nano-Collective#1727 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mahdi-Hasan
force-pushed
the
fix/1727-sanitize-webview-markdown
branch
from
November 4, 2026 06:42
3a4c462 to
b3ebbd0
Compare
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.
Description
Sanitizes every markdown render in the VS Code chat webview and stops remote image loads. Fixes #1727.
marked.parse()output is written toinnerHTML, not 3: user message, first agent chunk, throttled re-render, turn-end flush, and thoughts. All 5 now go through onesetMarkdown()helper, which renders via the newmedia/markdown-utils.js.markdown-utils.jsruns marked's output through DOMPurify 3.4.17. It ships asmedia/purify.min.jsthe same waymarked.min.jsdoes, byte-identical to the npm build.<style>,style=""or<form>.idandnameget auser-content-prefix.language-*. Without this, a reply could use the panel's Tailwind classes (e.g.fixed inset-0) to cover the UI.img-srcno longer allowshttps:. Pasted and uploaded images aredata:URIs, and nothing else in the panel loads remote images.Type of Change
Changeset
pnpm changeset) describing this change for the changelogTesting
Automated Tests
New features include passing tests in
.spec.ts/tsxfilesAll existing tests pass (
pnpm test:allcompletes successfully)Tests cover both success and error scenarios
plugins/vscode/src/markdown-utils.spec.ts(14 tests) loads the shipped marked, DOMPurify and helper into jsdom. It checks what gets removed, what still renders, the plain-text fallbacks, and the CSP. jsdom is a new devDependency of the extension only, and it isn't packaged because vsce runs with--no-dependencies.source/vscode/chat-panel-markdown.spec.ts(5 tests) drives the panel harness and checks that all 5 places are sanitized.Format, types (root and vscode), lint, knip and audit pass.
I developed this on Windows, where
pnpm test:avahas many failures onmaintoo (POSIX paths,spawn EINVAL). This branch adds no new failures. CI on Linux should settle it.Manual Testing
Checklist