# Unsandboxed Markdown in privileged renderer

Attacker Markdown rendered as live HTML/script in a webview or IDE origin that holds privileged APIs

_Area: Web injection and code execution. Seen in 3 disclosed reports; 2 confirmed bounties: $100 and $5,000; latest 2023-11-14. Updated 2026-10-23._

## How it works
A component takes attacker-influenced Markdown and renders it to HTML inside a context that already holds privilege: a web IDE origin, an Electron webview, or a trusted Markdown panel. The broken assumption is that Markdown is inert text. Renderers honor raw HTML, script, and `command:` links, so attacker content becomes live markup running with the host's origin and API access. The trust flag (`isTrusted`, `supportHtml`) is set on strings built from external data without sanitizing or escaping [E2](https://bugbountylibrary.com/r/blog%3Asonarsource-com-blog-vscode-security-markdown-vulnerabilities-in-extensions.md).

## Where it shows up
- Markdown preview, hover, or issue panels fed from Git data, issue text, or notebook cells [E1](https://bugbountylibrary.com/r/blog%3Aomespino-com-write-up-google-bug-bounty-xss-to-cloud-shell-instance-takeover-rce-as-root-5000-usd.md)[E2](https://bugbountylibrary.com/r/blog%3Asonarsource-com-blog-vscode-security-markdown-vulnerabilities-in-extensions.md)[E3](https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2022-10-27-jupytervscode-html.md)
- `isTrusted=true` / `supportHtml` set on strings interpolated from external data [E2](https://bugbountylibrary.com/r/blog%3Asonarsource-com-blog-vscode-security-markdown-vulnerabilities-in-extensions.md)
- Sandboxed iframes carrying both `allow-same-origin` and `allow-scripts` [E3](https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2022-10-27-jupytervscode-html.md)
- Electron `BrowserWindow` with `nodeIntegration` reachable from rendered content [E3](https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2022-10-27-jupytervscode-html.md)
- Escaping into a code fence that splits lines only on `\n` while the renderer also treats `\r` as a break [E2](https://bugbountylibrary.com/r/blog%3Asonarsource-com-blog-vscode-security-markdown-vulnerabilities-in-extensions.md)

## How to review
Trace every path where external data reaches a Markdown/HTML renderer. The invariant: rendered attacker content must run in an origin with no script access to privileged APIs, or be sanitized so no HTML, script, or `command:` link survives. Check the trust flag is never set on untrusted input; check sandbox flags never combine same-origin with scripts; check line-separator handling matches the renderer's. Treat file-download APIs and path traversal as separate chain primitives, not the renderer bug itself [E1](https://bugbountylibrary.com/r/blog%3Aomespino-com-write-up-google-bug-bounty-xss-to-cloud-shell-instance-takeover-rce-as-root-5000-usd.md)[E3](https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2022-10-27-jupytervscode-html.md).

## Variants seen
- Stored XSS in a web IDE markdown preview, chained with a file-URI download API and `../` traversal to leak an SSH key [E1](https://bugbountylibrary.com/r/blog%3Aomespino-com-write-up-google-bug-bounty-xss-to-cloud-shell-instance-takeover-rce-as-root-5000-usd.md)
- Trusted Markdown with a `\r` vs `\n` line-break differential escaping a code fence into a `command:` link that installs an extension [E2](https://bugbountylibrary.com/r/blog%3Asonarsource-com-blog-vscode-security-markdown-vulnerabilities-in-extensions.md)
- Notebook HTML XSS chained with a path traversal and permissive sandbox flags to reach nodeIntegration [E3](https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2022-10-27-jupytervscode-html.md)

## Impact and severity
Reached root on a cloud VM via leaked keys [E1](https://bugbountylibrary.com/r/blog%3Aomespino-com-write-up-google-bug-bounty-xss-to-cloud-shell-instance-takeover-rce-as-root-5000-usd.md), code execution via extension install [E2](https://bugbountylibrary.com/r/blog%3Asonarsource-com-blog-vscode-security-markdown-vulnerabilities-in-extensions.md), and RCE in the editor [E3](https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2022-10-27-jupytervscode-html.md). Severity is high because the renderer inherits host privilege; worse when file APIs, permissive sandbox flags, or nodeIntegration widen reach. E1 and E3 each required a separate traversal primitive to complete the chain.

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Aomespino-com-write-up-google-bug-bounty-xss-to-cloud-shell-instance-takeover-rce-as-root-5000-usd.md
- E2: https://bugbountylibrary.com/r/blog%3Asonarsource-com-blog-vscode-security-markdown-vulnerabilities-in-extensions.md
- E3: https://bugbountylibrary.com/r/blog%3Ablog-doyensec-com-2022-10-27-jupytervscode-html.md
