LearnNewsExamplesServices
Frontmatter
id18354
titleMonaco pins and bundles DOMPurify below the patched versions
stateClosed
labels
bugdependenciesaisecurity
assigneesneo-opus-grace
createdAtSep 5, 2026, 1:50 PM
updatedAtSep 15, 2026, 9:23 AM
githubUrlhttps://github.com/neomjs/neo/issues/18354
authorneo-gpt
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 15, 2026, 9:23 AM

Monaco pins and bundles DOMPurify below the patched versions

Closed v13.2.0/archive-v13-2-0-chunk-19 bugdependenciesaisecurity
neo-gpt
neo-gpt commented on Sep 5, 2026, 1:50 PM

Context

The operator reported four DOMPurify Dependabot alerts after the overnight dependency update. Live default branch dev at ea54d5ff89eef87cdb3ade0a2f0e17fdf79ca7bf contains:

  • mermaid@11.17.2 → dompurify ^3.3.3 → 3.4.13 (already above the four advisory floors).
  • monaco-editor@0.56.0 → dompurify 3.4.8 (exact pin; vulnerable nested lock entry).

The four open alerts all name package-lock.json, transitive development dependency dompurify:

Alert Advisory First patched version
222 GHSA-55q2-fjhq-7xh7 3.4.13
186 GHSA-c2j3-45gr-mqc4 3.4.12
164 GHSA-cmwh-pvxp-8882 3.4.11
155 GHSA-vxr8-fq34-vvx9 3.4.9

The alerts were created earlier and updated at 2026-09-05T00:49:36Z. This is the current affected dependency graph, not a claim that four advisories were newly published overnight.

The Problem

A dependency override can replace the installed nested npm package but cannot replace the sanitizer Monaco actually executes. The published Monaco distribution embeds its own DOMPurify copy.

Measured directly from the official monaco-editor-0.56.0.tgz:

  • esm/vs/base/browser/dompurify/dompurify.js carries DOMPurify 3.4.8.
  • esm/vs/base/browser/domSanitize.js imports that relative vendor module, not the npm dompurify package.
  • The distributed dev/vs/editor-ECyZhXSU.js and min/vs/editor-KLE6jdfb.js chunks also contain version 3.4.8.
  • Neo's src/main/addon/MonacoEditor.mjs#loadFiles loads node_modules/monaco-editor/min/vs directly.

Consequently, an npm-only override could make dependency scanners green while leaving the browser sanitizer unchanged.

This verifies affected-version presence, not a demonstrated XSS exploit in Neo. These advisories require specific hooks/configuration; no exploitability claim or blanket exemption is made here.

The Architectural Reality

DOMPurify is indirect but not absent from the editor: Monaco uses it for internal HTML/Markdown sanitization. The runtime source comes through VS Code's vendor copy. Upstream already reverted a dependency-only bump for this reason, and Monaco issue 5454 tracks the bundled-copy problem.

Registry verification on 2026-09-05: Monaco latest is 0.56.0, still pinned to 3.4.8. DOMPurify latest is 3.4.14; 3.4.13 meets all four listed advisory floors.

Existing root overrides in package.json addresses gray-matter/js-yaml, but that precedent does not alter already bundled JavaScript. No Engine API or ADR change is needed for a corrected upstream package.

The Fix

Current disposition: no corrected upstream distribution; a reproducible consumer-build candidate is now validated below. Keep the alerts visible until the selected production integration repairs both metadata and executed assets.

Upgrade the pinned Monaco package when its shipped editor assets and dependency metadata both contain patched DOMPurify, then regenerate the lockfile and verify the actual editor asset path.

If an earlier local remediation is required, it must be a reproducible Monaco build using patched DOMPurify at module resolution and a verified Neo loader/worker integration. That is a build integration choice, not a package-only override. Do not introduce minified-bundle surgery or an install-time patch as an implicit workaround.

Revalidation trigger: an upstream release/update on microsoft/monaco-editor#5454 or an explicitly selected local rebuild approach.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
Monaco dependency + lock entries npm metadata and four advisories above no DOMPurify entry in an affected range retain visible alerts while upstream is unpatched package metadata clean install and complete dependency-tree inspection
shipped Monaco sanitizer vendor module and AMD chunks in published tarball executed sanitizer is patched, not only the lockfile no scanner-only exemption remediation receipt on this ticket inspect shipped assets; browser uses those assets
Neo Monaco loader src/main/addon/MonacoEditor.mjs#loadFiles editor and workers still load through the selected distribution observable load failure existing addon JSDoc if integration changes browser create/edit/worker and sanitized-hover smoke

Acceptance Criteria

  • AC-1: A clean install resolves every DOMPurify lock entry above all four affected ranges; dependency output identifies the complete parent chains.
  • AC-2: Monaco's browser-loaded sanitizer is verified patched from the actual distributed/generated assets. A lockfile-only update does not satisfy this.
  • AC-3: Neo's Monaco editor boots, edits, and starts its language worker, with a sanitized HTML/Markdown rendering smoke and no new load failures.
  • AC-4: Post-merge: GitHub reevaluates alerts 155, 164, 186 and 222 as fixed by the dependency update; do not dismiss them to simulate remediation.

Out of Scope

Mermaid updates (its current sanitizer is already patched for these four alerts), replacing Monaco with another editor, unrelated dependency upgrades, and claiming exploitability from version matching alone.

Avoided Traps

  • An override that replaces an unused npm copy while the browser keeps executing the embedded old copy.
  • Downgrading Monaco to remove dependency metadata without checking its embedded sanitizer.
  • Assuming a dependency labeled development cannot reach the browser.
  • Editing third-party minified files manually.

Extended investigation — 2026-09-05

The published latest remains Monaco 0.56.0; next is 0.56.0-dev-20260625, whose metadata also pins DOMPurify 3.4.8. All four alerts remain open. Mermaid's installed 3.4.13 satisfies these four advisory floors.

Exposure in the inspected integration

The four advisories require, respectively: a prior custom Trusted Types policy on the reused instance; persistent setConfig() plus an allowlist-mutating attribute hook; custom-element handling plus an afterSanitizeElements policy; or IN_PLACE plus an element-removal hook. The shipped Monaco domSanitize.js builds per-call configuration, accepts string input, and does not configure those combinations. Its attribute predicate uses per-element keepAttr.

Executed the current Neo wrapper's AMD editor and JavaScript worker: diagnostics were empty; a custom HTML-capable Markdown hover removed event handlers and javascript: links, with no marker execution or page error. Separately instrumented the official ESM sanitizer: three exercised calls all used string input, no IN_PLACE, no custom-element configuration, no custom Trusted Types policy, and zero setConfig/clearConfig calls. This bounds the observed path; it does not certify every embedder or replace the dependency remediation.

Reproducible consumer-build candidate

A working alternative now exists. Using Monaco's official esbuild smoke-build pattern, compiled the published 0.56.0 ESM modules while resolving the vendor import in domSanitize.js to the official DOMPurify 3.4.14 ESM distribution. This substitutes a module at build time; no third-party source or minified bundle was edited.

  • The esbuild metadata proves the actual domSanitize.js → purify.es.mjs edge, with the old vendor module absent.
  • Generated editor JavaScript, CSS, font and all five standard worker entry points.
  • Browser candidate reports 3.4.14, boots the editor, reads its live model through the TypeScript worker, and passes the sanitized-hover smoke with zero page errors or failed asset responses.
  • Two builds with esbuild 0.28.2 produce the same editor bundle: 4,483,078 bytes, SHA-256 d02e1a8915eeb1bb4a6d7dd0961e4f4855cbb583d3c9534cc4ad700153c57410.

This is an isolated candidate, not the shipped Neo runtime. Production adoption still needs a maintained asset-build entry, Neo loader/worker URL integration, a patched dependency/lock graph, and the existing real-wrapper lifecycle tests against those generated assets. The candidate carries a diagnostic version export that would not be part of the production API. No repository files or alert dispositions changed during these probes.

The complete remediation can therefore proceed through a consumer build if upstream publication remains delayed; the current installed package continues to need repair.

Related

Monaco bundled sanitizer issue, upstream reverted metadata-only bump, DOMPurify 3.4.14 release.

Decision Record impact: none.

Origin Session ID: cb7ccc74-b375-4785-9adf-df6d1112957b

Retrieval Hint: Monaco 0.56.0 DOMPurify 3.4.8 bundled copy override alert 222 186 164 155

Creation freshness: live latest-20 open issue and all-status recent A2A sweeps immediately before filing found no equivalent ticket or competing claim. All-state DOMPurify issue search was empty. Semantic queries returned unrelated older material, so current GitHub, registry metadata, and published package bytes are the evidence.

tobiu unassigned from @neo-gpt on Sep 14, 2026, 8:22 PM
tobiu referenced in commit 4978b26 - "fix(monaco): the editor runs the DOMPurify npm resolves, built from Monaco's ESM sources (#18354) (#18717) on Sep 15, 2026, 9:23 AM
tobiu closed this issue on Sep 15, 2026, 9:23 AM