fix(desktop): support --no-sandbox when launched as uid 0#356
Merged
hqhq1025 merged 1 commit intoMay 23, 2026
Conversation
Two Chrome/Chromium spawn sites in the desktop app crash with
"Running as root without --no-sandbox is not supported" on the first
launch attempt:
1. apps/desktop/scripts/dev.cjs spawns Electron via electron-vite.
2. apps/desktop/src/main/preview-runtime.ts spawns Chrome via
puppeteer to render preview artifacts (used by 9 vitest cases).
This makes `pnpm dev` unusable and the preview-runtime test file fail
9 of 17 cases in any root-running environment (containers, dev VMs,
most CI images). The macOS/Windows/user-mode-Linux launch paths are
unaffected.
The dev wrapper now sets NO_SANDBOX=1 when uid is 0; electron-vite
already reads this env var and forwards --no-sandbox to Electron.
The preview-runtime launch args conditionally append --no-sandbox
under the same uid check.
Contributor
There was a problem hiding this comment.
Review mode: initial
Findings
No issues found.
Summary
This is a small, focused fix that adds --no-sandbox support for Electron and Puppeteer when launched as uid 0 (root). The changes are:
apps/desktop/scripts/dev.cjs(line 17–21): setsNO_SANDBOX=1env var whenprocess.getuid() === 0, whichelectron-vitealready forwards as--no-sandbox.apps/desktop/src/main/preview-runtime.ts(line 125–128): conditionally appends'--no-sandbox'to Puppeteer launch args when running as root.
Both changes are gated on process.getuid?.() === 0, so non-root behavior is completely unchanged (the same code path). The comments clearly explain the why per project conventions.
The PR satisfies all four PRINCIPLES checks:
- Compatibility ✅ — non-root paths untouched.
- Upgradeability ✅ — no schema, IPC, or config changes.
- No bloat ✅ — ~12 lines, no new dependencies.
- Elegance ✅ — consistent guard pattern at both call sites, inline with existing code.
No tests are added, but this is a internal dev-experience fix (not a shipped feature) and the PR description confirms the full test suite passes after the patch. That is appropriate given the scope.
Testing
- Not expanded (change is internal dev tooling). Existing CI passing after patch is sufficient.
Open-CoDesign Bot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two Chrome/Chromium spawn sites in the desktop app crash immediately when launched as uid 0, with:
apps/desktop/scripts/dev.cjs— spawns Electron via electron-vite.pnpm devexits within seconds, before the renderer can attach.apps/desktop/src/main/preview-runtime.ts— spawns Chrome via puppeteer-core to render preview artifacts. 9 of the 17preview-runtime.test.tscases fail as root, all with the same FATAL line in the failure payload.Both make the repo effectively unusable inside any rootful container, dev VM, or CI runner — environments where Node toolchains are commonly already root.
Fix
Gated to
process.getuid?.() === 0so the macOS / Windows / user-mode-Linux launch paths are unchanged:NO_SANDBOX=1, which electron-vite already reads and forwards as--no-sandboxto the spawned Electron process (seeelectron-vite/dist .../lib-q6ns0vZr.js:234).'--no-sandbox'to the puppeteer launch args.8 + 4 = 12 added lines, 2 files, no other code touched.
Verification
Local environment: Linux container, uid 0, Node 22.22.3, pnpm 10.33.4.
Before patch:
pnpm dev→[FATAL:electron_main_delegate.cc:216] Running as root without --no-sandbox is not supported.pnpm --filter @open-codesign/desktop test→Test Files 1 failed | 109 passed (110),Tests 9 failed | 1332 passed (1341)— every failure points back to the same FATAL line.After patch:
pnpm dev→ Electron now reachesMissing X server or $DISPLAY(expected on a headless box; out of scope for this PR).pnpm -r typecheck✅,pnpm lint✅ (Biome, 524 files),pnpm test✅ 110/110 files, 1341/1341 tests (vs 9 failing onmain).Principles check
getuid?.() === 0guard; comments explain why (per CLAUDE.md).No changeset added — this is an internal dev-experience fix that doesn't change shipped behavior. Happy to add one if the project prefers.