6b3a7af73d
Review follow-up on #84203. Both points reproduce; neither was a regression from the first pass, but both are live bypasses of the same guard. **Privilege and namespace wrappers were missing.** The allowlist covered the coreutils-shaped wrappers but not the privilege ones, so each of these ran a lifecycle script straight past the walk: pkexec bash ~/restart.sh runuser -u root -- bash ~/restart.sh setpriv --reuid=0 -- bash ~/restart.sh systemd-run --scope bash ~/restart.sh nsenter --target 1 --mount bash ~/restart.sh unshare -r bash ~/restart.sh Added `pkexec`, `su`, `runuser`, `setpriv`, `systemd-run`, `nsenter` and `unshare`, each with the value-taking options that would otherwise be mistaken for the command (`nsenter -t 1`, `systemd-run -p X=1`, `runuser -u root`, …). **An option can carry a command STRING, not an argv tail.** `env -S` and `su`/`runuser` `-c` take shell source. The peel treated the operand as an opaque value and skipped it, so `env -S 'bash ~/restart.sh'` was never scanned — the string went unread rather than being recursed into. `_STRING_COMMAND_OPTIONS` now names those options and their values are re-scanned as shell source, the same treatment `sh -c` payloads already get. They are read at the ORIGINAL command token, before the transparent-prefix peel, because peeling past `su`/`env` would discard the very option carrying the command. `--opt value` and `--opt=value` are both handled. Scope, stated plainly: this is an enumerated allowlist, not a general solution to "wrapper that execs its tail". A wrapper outside the set, or a value-taking option outside these tables, still resolves to no reference — that fails open, exactly as it did before this PR, and it is a miss rather than a false block. The reviewer offered "extend the set with tests, or document that the list is heuristic"; this does the first and states the second. Tests: 23 new cases (220 in the file) — every added wrapper against a script reference including the value-operand option forms, both command-string option spellings for env/su/runuser, and the same wrappers around ordinary work (`pkexec systemctl status nginx`, `su -c 'ls -la'`, `env -S 'echo hi'`, `nsenter -t 1 -m ps aux`) which must stay allowed. 15 fail on the tree before this commit. False positives re-checked at scale: the 9,258 command lines from this repo's own scripts and docs give an identical verdict set before and after — 0 new false positives, 0 lost detections, 0 exceptions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011cSddnhxiUmdGbgyKnpg8p