Skip to content
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
44bad43
feat(cef): real Linux sandbox-enable attempt (no_sandbox=false)
qnbs Aug 19, 2026
952996a
fix(cef): assert no sandbox-weakening flags on the real process comma…
qnbs Aug 19, 2026
f2a034f
fix(cef): real root cause of the sandboxed-launch failure + harness h…
qnbs Aug 19, 2026
ff87752
research(cef): isolate whether Yama ptrace_scope blocks Crashpad unde…
qnbs Aug 19, 2026
0d3914b
research(cef): separate sandbox-enforcement evidence from Crashpad re…
qnbs Aug 19, 2026
205c03b
research(cef): capture NSpid + event-driven snapshot for the PID-name…
qnbs Aug 19, 2026
eb0bd6d
research(cef): compare real pid-ns identity, not just NSpid nesting d…
qnbs Aug 19, 2026
f00022f
research(cef): add PPid/ns/pid_for_children capture + browser-vs-hand…
qnbs Aug 19, 2026
3c08bf0
fix(cef): three real diagnostic-harness bugs caught in review before …
qnbs Aug 19, 2026
3fae0f8
fix(cef): correct handler identity — --type= authoritative, cmdline s…
qnbs Aug 19, 2026
1abf94e
fix(cef): handle Chromium's argv-rewrite for zygote-forked children i…
qnbs Aug 19, 2026
826253f
feat(cef): promote sandbox-status proof to a real renderer-specific a…
qnbs Aug 19, 2026
ae45ac7
docs(cef): reconcile Wave 2 docs with real sandbox-enable + Crashpad …
qnbs Aug 19, 2026
b8b7bcf
fix(cef): address CodeRabbit nitpicks — bound summary output, scope b…
qnbs Aug 19, 2026
08b2dab
fix(cef): correct future-dated evidence records + scope handlers by h…
qnbs Aug 19, 2026
3dfc711
fix(cef): correct chrome-sandbox invocation overclaim across all docs
qnbs Aug 19, 2026
2812775
fix(cef): real fix attempt for renderer-crash-dump-under-sandbox (R-19)
qnbs Aug 19, 2026
7764659
research(cef): real root-cause-informed --no-zygote experiment for R-19
qnbs Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 49 additions & 5 deletions .github/workflows/cef-learning-harness.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,13 @@ jobs:
- name: List worldscript_host output directory (diagnostic)
run: ls -la build/worldscript_host/

# QNBS-v3: CEF's own COPY_FILES step copies chrome-sandbox with normal permissions — real CI evidence (PR #404) showed Chromium's setuid_sandbox_host.cc treats a present-but-misconfigured helper as FATAL rather than silently falling back to unprivileged user namespaces, so this standard CEF/Chromium packaging step (chown root + mode 4755) is required before any sandboxed launch, matching how a real .deb/AppImage installer would need to set this up too.
- name: Set up SUID sandbox helper (chrome-sandbox)
run: |
sudo chown root:root build/worldscript_host/chrome-sandbox
sudo chmod 4755 build/worldscript_host/chrome-sandbox
ls -la build/worldscript_host/chrome-sandbox

- name: Linux runtime linkage check (ldd against shipped .so files)
run: node scripts/cef/check-linux-runtime-linkage.mjs build/worldscript_host

Expand Down Expand Up @@ -207,31 +214,63 @@ jobs:
run: |
python3 -m http.server 8080 --directory dist &
SERVER_PID=$!
# QNBS-v3: GitHub Actions runs bash steps with -e by default — a failing node proof would previously skip the plain `kill` below entirely, leaking the http.server past this step. Real gap found alongside PR #404's sandbox work; applied here too, not just the new step.
trap 'kill "$SERVER_PID" 2>/dev/null || true' EXIT
sleep 1
xvfb-run -a node scripts/cef/run-launch-cycle-proof.mjs \
"$(pwd)/build/worldscript_host/worldscript_host" \
"http://localhost:8080/" --cycles 3
kill "$SERVER_PID"
"http://localhost:8080/" --cycles 3 --skip-crash-reporting

# QNBS-v3: real CI evidence (PR #404) — split out from the step above since the two are genuinely independent facts (roadmap review guidance): "sandbox enforcement" and "sandbox-compatible Crashpad renderer-crash-dump generation" must never be conflated into one pass/fail signal. Runs at the REAL, unmodified ptrace_scope (no Yama relaxation — that was a one-time diagnostic A/B experiment, never a steady-state fix) so this honestly reports the production-representative outcome. continue-on-error because this is a real, currently-open, well-diagnosed regression (prctl(PR_SET_PTRACER) EINVAL, likely a PID-namespace-relative mismatch between the sandboxed renderer and the crash handler — see cef-architecture-primer.md), not yet solved.
- name: Crash-reporting proof under real sandbox (known Crashpad/PID-namespace limitation — tracked separately)
id: crash-reporting-under-sandbox
continue-on-error: true
run: |
python3 -m http.server 8083 --directory dist &
SERVER_PID=$!
trap 'kill "$SERVER_PID" 2>/dev/null || true' EXIT
sleep 1
xvfb-run -a node scripts/cef/run-launch-cycle-proof.mjs \
"$(pwd)/build/worldscript_host/worldscript_host" \
"http://localhost:8083/" --only-crash-reporting
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

- name: Crash-symbolization proof (dump_syms + minidump-stackwalk)
# QNBS-v3: crashes the browser process itself (--debug-crash-self), which is never sandboxed by CEF's own design (see cef-architecture-primer.md) — independent of the renderer/Crashpad-under-sandbox finding above, so this must still run and report its own real result regardless of that step's outcome.
if: always()
run: |
xvfb-run -a node scripts/cef/run-symbolization-proof.mjs \
"$(pwd)/build/worldscript_host/worldscript_host" \
"$DUMP_SYMS_BIN" \
"$MINIDUMP_STACKWALK_BIN"

- name: Real Linux sandbox-status proof (no_sandbox=false)
id: sandbox-status
# QNBS-v3: first real attempt, genuinely unverified against live CI — continue-on-error keeps a failure here from also blocking the Wayland smoke step below (same lesson as the accessibility PR #391→#397 regression); remove once this has real, reliable green evidence. if: always() since this step's own evidence (sandbox enforcement) is independent of the crash-reporting step above.
continue-on-error: true
if: always()
run: |
set -o pipefail
python3 -m http.server 8082 --directory dist &
SERVER_PID=$!
trap 'kill "$SERVER_PID" 2>/dev/null || true' EXIT
sleep 1
xvfb-run -a node scripts/cef/run-sandbox-status-proof.mjs \
"$(pwd)/build/worldscript_host/worldscript_host" \
"http://localhost:8082/" | tee "$RUNNER_TEMP/cef-sandbox-status.txt"

- name: Best-effort Wayland launch smoke (roadmap §44.2)
id: wayland-smoke
continue-on-error: true
if: always()
run: |
sudo apt-get install -y weston
python3 -m http.server 8081 --directory dist &
SERVER_PID=$!
trap 'kill "$SERVER_PID" 2>/dev/null || true' EXIT
sleep 1
node scripts/cef/run-wayland-smoke.mjs \
"$(pwd)/build/worldscript_host/worldscript_host" \
"http://localhost:8081/"
kill "$SERVER_PID"

- name: Summary
if: always()
Expand All @@ -243,9 +282,14 @@ jobs:
echo "- worldscript_host built and repeated launch/close cycles proven against the real production bundle (dist/), under Xvfb." >> "$GITHUB_STEP_SUMMARY"
echo "- Linux runtime linkage (ldd against the shipped worldscript_host + libcef.so, not just dpkg package presence): see the \"Linux runtime linkage check\" step above." >> "$GITHUB_STEP_SUMMARY"
echo "- Crash-symbolization proof: a self-induced browser-process crash resolved via dump_syms + minidump-stackwalk against our own DWARF debug info — Chromium/CEF-internal frames remain unsymbolized (no debug-symbols archive is published for this distribution)." >> "$GITHUB_STEP_SUMMARY"
echo "- Linux sandbox feasibility inventory (diagnostic only, no sandbox behavior attempted yet):" >> "$GITHUB_STEP_SUMMARY"
echo "- Linux sandbox feasibility inventory (diagnostic only, pre-dates the real enable attempt below):" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
cat "$RUNNER_TEMP/cef-sandbox-inventory.txt" >> "$GITHUB_STEP_SUMMARY" 2>/dev/null || echo "(inventory output unavailable)" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
echo "- **Sandbox enforcement** (no_sandbox=false, per-process Seccomp/NoNewPrivs/user-ns evidence): \`${{ steps.sandbox-status.outcome }}\`" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
cat "$RUNNER_TEMP/cef-sandbox-status.txt" >> "$GITHUB_STEP_SUMMARY" 2>/dev/null || echo "(sandbox-status output unavailable)" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
echo "- **Sandbox-compatible Crashpad renderer-crash-dump generation** (real ptrace_scope, no diagnostic relaxation — a currently-open, separately-tracked regression, not conflated with sandbox enforcement above): \`${{ steps.crash-reporting-under-sandbox.outcome }}\`" >> "$GITHUB_STEP_SUMMARY"
echo "- Wayland smoke (best-effort, roadmap §44.2): \`${{ steps.wayland-smoke.outcome }}\`" >> "$GITHUB_STEP_SUMMARY"
echo "- Not yet in scope: X11/Wayland matrix beyond this one runner, sandbox posture, accessibility-tree observability (AT-SPI — state enablement is proven, see the launch-cycle-proof step)." >> "$GITHUB_STEP_SUMMARY"
echo "- Not yet in scope: X11/Wayland matrix beyond this one runner, full real-hardware/GPU/display-server sandbox matrix, accessibility-tree observability (AT-SPI — state enablement is proven, see the launch-cycle-proof step)." >> "$GITHUB_STEP_SUMMARY"
8 changes: 7 additions & 1 deletion apps/desktop-cef/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,13 @@ int main(int argc, char* argv[]) {
InstallShutdownSignalHandlers();

CefSettings settings;
settings.no_sandbox = true; // ADR-0020: sandbox posture deliberately deferred (roadmap §12).
// QNBS-v3: real sandbox-enable attempt (Wave 2 exit criterion) — ADR-0020's spike ran with
// no_sandbox=true unconditionally; PR #402's feasibility inventory confirmed unprivileged
// user-namespace sandboxing is functionally reachable on the CI runner (unshare succeeded),
// so this attempt lets CEF/Chromium's own sandbox init run for real rather than assuming it
// would fail. scripts/cef/run-sandbox-status-proof.mjs reads real per-process evidence
// (Seccomp/NoNewPrivs, user-namespace identity) rather than trusting a clean launch alone.
settings.no_sandbox = false;

// QNBS-v3: CefInitialize's return value was previously ignored, masking init failure (missing display/resources) as a normal exit — CodeAnt review finding on PR #388.
if (!CefInitialize(main_args, settings, app.get(), nullptr)) {
Expand Down
Loading
Loading