Security1 distinct publisher3 min readUpdated
ProjectDiscovery says an audit of Markdown Preview Enhanced turned an ordinary repository file into arbitrary file write. Editor extensions run with developer privileges and go uninventoried.
The Watch · Security desk
Compiled by The WatchSomething wrong?How this is made
ProjectDiscovery has published an audit of Markdown Preview Enhanced, a VS Code extension with roughly 9.5 million installs, reporting five CVEs across two attack surfaces, all now fixed [1] [2]. The reason to care is not the Markdown parser: editor extensions auto-update and run with a developer's privileges on the machine that holds the source code, the SSH keys and the publishing credentials, and they rarely appear in a software bill of materials [3].
The first chain starts in the renderer. Before the fix, the WaveDrom diagram renderer took the raw text of a WaveDrom block and evaluated it as JavaScript through `window.eval` [4]. That text comes straight from the Markdown file, so opening a crafted file and rendering the preview is enough; there is no code-chunk opt-in and no setting to enable [5].
The extension did sanitize. After an earlier XSS fix it added Cheerio and DOMPurify passes, but diagram renderers need their data preserved, so the sanitizer kept a small allowlist of script-like diagram types, `wavedrom` and `text/tikz`, and let the WaveDrom carrier through [6]. Sanitization held at one layer; a later feature treated the preserved content as code anyway [7].
Execution inside a preview is, on its own, webview XSS [8]. The damage is at the second boundary. VS Code isolates webviews from the extension host, and the two talk via `postMessage`, which is only safe if the host treats those messages as untrusted [9]. This host did not: it built both the command name and its arguments from the incoming message and handed them to `vscode.commands.executeCommand` [10]. One reachable command, `_crossnote.updateMarkdown`, parsed a caller-supplied URI and wrote content to it with no workspace containment check, which means any `file://` URI and any content [11]. Four links: Markdown reaches `eval`, the injected script recovers the webview API handle the preview already holds, that handle reaches command dispatch, and dispatch lands on arbitrary file write [12]. That is CVE-2026-50733, fixed in v0.8.28 [13].
The two pieces of shared plumbing are independently dangerous, because any JavaScript running in the webview can reach them, not only WaveDrom [14]. They were filed separately as CVE-2026-54702 and CVE-2026-54703 [15]. An unsanitized HTML injection supplied a second XSS entry point, CVE-2026-54701 [16]. And two entry points needed no Markdown at all: the extension loads `.crossnote/config.js` and `.crossnote/parser.js` from any workspace that contains them, and a VM sandbox escape gave a workspace configuration file direct OS command execution, CVE-2026-54566, fixed in v0.8.29 [17] [18].
That is the part that should change how you think about your dependency inventory. The delivery vehicle here is not a poisoned npm package with a version string you can diff; it is a file sitting in a repository you cloned, executed by a tool that updated itself last week and that no manifest lists [3] [19]. The fixes span two releases, so anything below v0.8.29 is missing at least one of the five disclosed patches [20].
Worth tracking: the minimum extension version present across developer laptops and CI images, and whether your asset inventory has a field for editor extensions at all. The bug class also generalises beyond this vendor, since it is host-side code trusting messages from a sandbox it deliberately created [9]; any extension that dispatches commands from `postMessage` payloads is running the same design.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
A VM sandbox escape gave a workspace configuration file direct OS command execution, tracked as CVE-2026-54566 and fixed in v0.8.29.
ProjectDiscovery audited the VS Code extension Markdown Preview Enhanced, which has roughly 9.5 million installs, using its tool Neo.
The audit found five CVEs across two attack surfaces, and all five are now fixed.
Code editor extensions auto-update and run with the user's privileges on the machine that holds their source code, SSH keys and publishing credentials, but they rarely show up in a software bill of materials.
Before the fix, the Markdown Preview Enhanced WaveDrom renderer took the raw text of a WaveDrom block and evaluated it as JavaScript with the call const content = window.eval(`(${text})`).
The evaluated text comes straight from the Markdown file, so opening a crafted file and rendering the preview reaches the path, with no code-chunk opt-in and no setting to enable.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Detailed but single-source and vendor-authored
The write-up supplies vulnerable code excerpts, the sanitizer allowlist, the postMessage dispatch, a working sandbox-escape proof of concept, five CVE identifiers and specific fix versions, which is unusually concrete technical evidence. It is nevertheless one vendor post with no independent confirmation, no linked CVE records in the supplied material, and no maintainer statement, so verification rests entirely on the discloser.
Large install base and shipped patches, uptake unknown
The affected component is broadly deployed (~9.5M installs) and remediation has actually shipped in v0.8.28 and v0.8.29, both concrete adoption-relevant facts. What is unmeasured is how much of that base has updated, and the source reports no exploitation in the wild, so real-world impact cannot be scored higher.
Slightly overstated framing on solid technical ground
The 'supply-chain foothold' and headline install-count framing is broader than what is demonstrated: the flaws require opening attacker-supplied Markdown or a workspace containing a crafted .crossnote file, all five issues are already patched, and no exploitation is reported. The underlying findings are well documented, so the gap is modest and driven mainly by the vendor's incentive to showcase its Neo tool.
Vendor-authored capability demonstration
The sole publisher is the security vendor whose commercial tool, Neo, is credited with finding the bugs; the post's structure ('How Neo found it') makes it both disclosure and product marketing. That does not undermine the code-level findings, but it gives the publisher a direct interest in maximal framing of severity and reach.
Technically credible, corroboration absent
Internal consistency and code specificity are high, and fix versions are checkable in principle, but the cluster contains exactly one interested publisher, no second report, no maintainer or CVE-registry confirmation in the supplied material, and no patch-uptake or exploitation data. That combination supports moderate confidence in the technical claims and low confidence in the broader impact framing.
build
One event per token: the fix went in the proxy, because that was the only box he owned1 distinct publisher
science
OX Security says MCP command execution is a design choice, so server owners own the risk1 distinct publisher
build
Your Coding Agent Reads .env, And .gitignore Was Never The Control1 distinct publisher
build
Shadow AI now has an invoice: about $670K on top of the average breach1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
1 article · August 16, 2026