Skip to content

Sanitize HTML in our VS Code panels - #3675

Open
Andrew Casey (amcasey) wants to merge 4 commits into
mainfrom
amcasey/docview
Open

Sanitize HTML in our VS Code panels#3675
Andrew Casey (amcasey) wants to merge 4 commits into
mainfrom
amcasey/docview

Conversation

@amcasey

Copy link
Copy Markdown
Member

We don't expect our extension to be activated unless the user has explicitly trusted the workspace, but it's good defence in depth to sanitize the HTML anyway. The affected panels are:

  • API Documentation
  • Estimates
  • Histogram
  • Circuit
  • Help

Bonus: sanitize in the playground too. It only loads content we've authored, but it seemed preferable to be consistent (and may protect us from automated security scans in the future).

...and add CSP for added protection.
This is overbroad, but the trusted content appearing in places other than the doc panel should already be sanitized, so this should be a no-op.
@amcasey

Copy link
Copy Markdown
Member Author

Vibe-coded but reviewed and tested by me.

@amcasey

Copy link
Copy Markdown
Member Author

No idea what I clicked to remove non-copilot reviewers. 🤷

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new markdown-it { html: false } setting will break existing kata/doc markdown that relies on inline HTML, and there are remaining http:// links that will be stripped by the new URI allowlist.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR hardens HTML rendering in the QDK VS Code extension webviews (documentation, estimates, histogram, circuit, help) and the playground, aiming to reduce XSS risk by tightening CSP and sanitizing rendered markdown.

Changes:

  • Add a Content Security Policy to the VS Code panel host HTML and remove reliance on inline scripts.
  • Sanitize markdown rendering in the VS Code webview bundle and the playground via DOMPurify, with a protocol allowlist.
  • Update a kata link from http:// to https:// to comply with the new link sanitization policy.
File summaries
File Description
source/vscode/src/webviewPanel.ts Adds CSP to the shared panel HTML and passes resource URI via a DOM attribute instead of an inline script.
source/vscode/src/webview/webview.tsx Introduces DOMPurify-based sanitization for rendered markdown and adjusts markdown-it configuration.
source/vscode/src/webview/help.tsx Switches help panel resource URI lookup from a global injected variable to data-resources-uri.
source/playground/src/main.tsx Mirrors the DOMPurify + markdown-it sanitization approach used by the VS Code webview.
katas/content/linear_algebra/index.md Updates an external link to HTTPS to remain valid under stricter URI sanitization.
Review details

Suppressed comments (2)

source/vscode/src/webview/webview.tsx:37

  • The URI allowlist regex does not include http:. There is still at least one http:// link in kata content (katas/content/teleportation/index.md:11), so DOMPurify will strip or neutralize that link when rendering markdown. Either migrate remaining http:// links to https:// or temporarily allow http: here to avoid breaking content.
// Allow only the protocols used in doc/kata/estimator content
// Borrowed from DOMPurify and filtered to our protocols
const ALLOWED_URI = /^(?:(?:https|xref):|[^a-z]|[a-z+.-]+(?:[^a-z+.-:]|$))/i;
setRenderer((input: string) =>
  DOMPurify.sanitize(md.render(input), { ALLOWED_URI_REGEXP: ALLOWED_URI }),

source/playground/src/main.tsx:71

  • The URI allowlist regex does not include http:. Since there is still at least one http:// link in kata content (katas/content/teleportation/index.md:11), it will be stripped/neutralized when rendered in the playground. Either migrate remaining http:// links to https:// or temporarily allow http: in the allowlist to avoid breaking content.
// Allow only the protocols used in doc/kata/estimator content
// Borrowed from DOMPurify and filtered to our protocols
const ALLOWED_URI = /^(?:(?:https|xref):|[^a-z]|[a-z+.-]+(?:[^a-z+.-:]|$))/i;
setRenderer((input: string) =>
  DOMPurify.sanitize(md.render(input), { ALLOWED_URI_REGEXP: ALLOWED_URI }),
  • Files reviewed: 5/5 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


const md = markdownIt("commonmark");
import DOMPurify from "dompurify";
const md = markdownIt("commonmark", { html: false });
Comment on lines 13 to 17
// Ensure that the fetch is kicked off once for the module
if (!svgPromise) {
const resourcesUri = document.body.dataset.resourcesUri ?? "";
svgPromise = fetch(`${resourcesUri}/DebugDropDown.svg`);
}
import mk from "@vscode/markdown-it-katex";
import markdownIt from "markdown-it";
const md = markdownIt("commonmark");
const md = markdownIt("commonmark", { html: false });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants