Linux desktop app.relaunch() sets NoNewPrivs on relaunch helper; inherited flag blocks sudo in full-access sessions
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
What version of the Codex App are you using?
Linux desktop Debian package chatgpt 26.903.71938, bundled codex-cli 0.153.4.
Native runtime process.versions.chrome and .electron both report 152.0.7977.83. The package's /usr/lib/chatgpt/version file says 42.3.0, so that file alone is not a reliable identification of this runtime.
What subscription do you have?
Not included; this reproducer does not require an account or model call.
What platform is your computer?
Debian, Linux 6.19.14+deb14-amd64 x86_64 GNU/Linux.
What issue are you seeing?
The Linux desktop main process has NoNewPrivs: 1, inherited by its Codex app-server and command shells, including a full-access session with sandbox disabled. sudo -n su -c id fails with:
sudo: The "no new privileges" flag is set, which prevents sudo from running as root.
The user reports passwordless sudo works in their ordinary desktop terminal. The same main-process PID remains running from an earlier app restart, so this investigation has not yet measured a fresh desktop launch from a NoNewPrivs: 0 terminal.
I dynamically verified a call that explicitly sets this restriction on the installed native runtime’s relaunch path: an isolated minimal app calling app.relaunch() makes the child execute prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) immediately before exec of the --type=relauncher helper. That helper launches the replacement main app, which inherits the irreversible restriction.
What steps can reproduce the bug?
Copy the native executable and its supporting runtime files into a disposable directory, keeping the installed app untouched. In a separate source directory, create package.json containing {"name":"nnp-relaunch-test","version":"1.0.0","main":"main.js"} and the following main.js; pack those two files as the disposable runtime’s resources/app.asar (e.g. with the Electron ASAR packaging tool). Use a separate --user-data-dir and export a disposable log path in NNP_TEST_LOG. Do not copy the real application bundle into the test runtime, replace the installed app’s resources, or restart an active work session:
const { app } = require('electron');
const fs = require('fs');
const phase = process.argv.includes('--nnp-phase-two')
? 'after-relaunch' : 'before-relaunch';
fs.appendFileSync(process.env.NNP_TEST_LOG, JSON.stringify({
phase,
pid: process.pid,
ppid: process.ppid,
status: fs.readFileSync('/proc/self/status', 'utf8')
.match(/^NoNewPrivs:.*$/m)[0],
versions: process.versions
}) + '\n');
if (phase === 'before-relaunch') {
app.relaunch({ args: process.argv.slice(1).concat(['--nnp-phase-two']) });
}
app.exit(0);
Trace with strace -f -s 300 -e trace=prctl,execve,clone,fork,vfork -o trace.log /path/to/isolated/ChatGPT --user-data-dir=/path/to/disposable/profile.
Observed trace excerpt (paths shortened; runtime binary unchanged):
264427 prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) = 0
264427 execve(".../runtime/ChatGPT", [".../runtime/ChatGPT", "--type=relauncher", "--no-sandbox", "---", ".../runtime/ChatGPT", "--user-data-dir=.../profile", "--nnp-phase-two"], ...) = 0
264429 execve(".../runtime/ChatGPT", [".../runtime/ChatGPT", "--user-data-dir=.../profile", "--nnp-phase-two"], ...) = 0
The --no-sandbox helper argument is generated internally by app.relaunch(); it was not supplied to the initial app. No security flags or native binary code were modified.
Both phases reported NoNewPrivs: 1 because the diagnostic shell already inherited that flag. This is a direct trace of the setter on the relaunch path, not a claimed measurement of a 0→1 transition or proof of the historical syscall for the live desktop process. A maintainer should repeat from a normal NoNewPrivs: 0 shell and compare fresh start vs relaunch.
What is the expected behavior?
A normal desktop app restart should preserve the main app's existing privilege state, so an explicitly full-access Codex session does not unexpectedly lose the ability to use authorized sudo after restart. Sandboxed renderers and intentionally restricted command sessions should retain their security restrictions.
Additional information
- Tested a copied native binary with SHA-256 identical to the installed executable:
fda09eaccd809821e71b33275bd20cac20b8bd587f1756471fb705cd59e4542d. - This native runtime emits source paths under
owl/browser/api/, so attributing it exclusively to stock Electron 42.3.0 would be inaccurate. - Inspected public
openai/codexat9e22e74e8dcab53f8bf1799c0eed1f9834c32f1a. The relevant native desktop relaunch implementation is not present there. The Rust Linux sandbox's deliberate NNP use should not be removed to treat an inherited parent-process flag; Linux cannot clear an inherited NNP flag. - Please route to the Linux desktop/Owl runtime relaunch owner. A narrow fix should preserve the parent's existing NNP state for the browser/main-process relaunch only, with a regression test starting from NNP=0. I have not supplied a speculative patch against unrelated public CLI code.
- Searched existing reports for
NoNewPrivs,"no new privileges", and Linux relaunch/sudo. #7577 concerns ordinary CLI sandbox warnings; #8222 concerns a systemd-launched CLI. Neither documents this dynamically traced desktop relaunch path.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Linux desktop/Owl runtime relaunch path behind app.relaunch(), since the relevant implementation is not in public openai/codex. Reproduce from a normal NoNewPrivs: 0 shell with the isolated app and strace command, comparing fresh launch with relaunch. Done means the browser/main-process relaunch preserves the parent's existing NNP state while restricted sessions retain their restrictions, with a regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- electron, linux, rust
- Domain
- desktop-dev, operating-systems, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100