diff --git a/CHANGELOG.md b/CHANGELOG.md index cf336b8c5..ac7a4c5c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ versioned entry and uses it as the GitHub release notes. - Prevent unauthenticated remote code execution on `/tikz/svg` via `\special{ps:...}`: `dvisvgm` hands PostScript specials embedded in the DVI off to Ghostscript, which `dvisvgm` starts with `-dDELAYSAFER` instead of `-dSAFER`, leaving the `%pipe%` device available and allowing arbitrary command execution regardless of `KROKI_SAFE_MODE` — including `SECURE`, since that setting only restricts kpathsea (LaTeX) file access and has no effect on Ghostscript. Fixed by passing `--no-specials=ps` to `dvisvgm` so PostScript specials are never processed - Prevent BPMN diagram source from executing arbitrary HTML/JavaScript in the companion's headless Chromium page: the diagram source was assigned to the rendering container via `innerHTML` before being handed to bpmn-js, so a crafted request to `/bpmn/svg` could inject an element (e.g. ``) that ran script in that page; combined with the browser's `--disable-web-security` flag (same-origin policy disabled), that script could issue cross-origin requests and read the responses. Fixed by clearing the container instead of parsing the diagram source as HTML, and by dropping `--disable-web-security` — the only reason it was set, local file access, is already covered by the shared `--allow-file-access-from-files` flag ([#2089](https://github.com/yuzutech/kroki/pull/2089)) +- Stop the headless Chromium instance shared by the Mermaid, BPMN, Excalidraw and diagrams.net companions from phoning home to Google (`update.googleapis.com`, `clients2.google.com`, `android.clients.google.com`, `accounts.google.com`, `www.google.com`) as soon as it launches: several independent Chromium subsystems (GCM device checkin, network-time sync, the component updater, ...) each reach out to their own Google endpoint, so disabling them one flag at a time (`--disable-component-update`, `--disable-domain-reliability`, `--no-pings`) still left some contacting Google — confirmed by packet capture. Fixed by blocking DNS resolution for those exact hosts at the browser level via `--host-resolver-rules` — not a `*.google.com`/`*.googleapis.com` wildcard, so it doesn't also block legitimate diagram-triggered subresources under the same domains (e.g. `fonts.googleapis.com`), which remain governed by the existing `KROKI_*_SAFE_MODE`/`*_ALLOWED_ORIGINS` request policy ### Changed diff --git a/lib/browser-instance/index.js b/lib/browser-instance/index.js index 950ac8400..5d9933e01 100644 --- a/lib/browser-instance/index.js +++ b/lib/browser-instance/index.js @@ -22,6 +22,36 @@ const BASE_ARGS = [ '--disable-dev-shm-usage', // Disable the setuid sandbox (Linux only) '--disable-setuid-sandbox', + // Puppeteer's own default args (see ChromeLauncher.defaultArgs) already cover + // most background chatter (--disable-background-networking, --disable-sync, + // safe browsing, etc.), but several independent Chromium subsystems still + // phone home to Google on browser launch regardless: GCM device checkin + // (android.clients.google.com), network-time/CUP sync (clients2.google.com, + // www.google.com), account status (accounts.google.com), and the component + // updater (update.googleapis.com) — confirmed by packet capture even with + // --disable-component-update/--disable-domain-reliability/--no-pings set. + // Disabling each subsystem individually is whack-a-mole across Chromium + // versions, so instead block DNS resolution for the exact hosts confirmed + // by packet capture. Listed individually rather than as a *.google.com / + // *.googleapis.com wildcard so this doesn't also swallow legitimate + // diagram-triggered subresources under the same domains (e.g. + // fonts.googleapis.com) — those are already gated by applyNetworkPolicy + // below (KROKI_*_SAFE_MODE / *_ALLOWED_ORIGINS), which is the right layer + // to opt into them. Extend this list if packet capture turns up another + // Google host doing this. + '--disable-component-update', + '--disable-domain-reliability', + '--no-pings', + '--host-resolver-rules=' + + [ + 'update.googleapis.com', + 'clients2.google.com', + 'android.clients.google.com', + 'accounts.google.com', + 'www.google.com' + ] + .map(host => `MAP ${host} 127.0.0.1`) + .join(','), // Run in headless mode, i.e., without a UI or display server dependencies '--headless', // Prevents creating scrollbars for web content. Useful for taking consistent screenshots.