`shell-curl-pipe-shell` hard-codes `bash|zsh|dash|fish|sh` in the download-pipe
matcher while the structural `env` fallback reads `_SHELL_NAMES`. The two lists
drift: `curl ... | ksh` (and csh/tcsh/ash/mksh) pipes a fetched script in
silence, even though sandbox_audit_middleware already treats ksh as a shell.
Derive the alternation from `_SHELL_NAMES` and widen both to the same ten
names, so a shell added once is visible to both detectors.
* fix(skillscan): catch a shell behind a sudo option that takes a value
`shell-curl-pipe-shell` skips a leading `sudo` and its standalone flags, but
`| sudo -u deploy bash` left the matcher parked on the option value, so a
remote script piped into a shell went unreported. Let a value-taking sudo
option consume its value as well.
* fix(skillscan): keep the sudo option branches mutually exclusive
A chain of value-taking options (`curl ... | sudo -u -u -u ... cat`) matched both sudo alternatives inside the lazy repeat, so re.search explored every one-/two-token partition before the non-shell tail failed: a 211-byte input took exponential time and did not return. Excluding value-taking options from the standalone branch lets each token be consumed exactly one way, so a failing chain stays linear while `sudo -u deploy bash` and `sudo -E bash` still report.
* fix(skillscan): treat `sudo -h` as taking a value in the download pipe
The hand-maintained class of sudo options that take a separate value
missed `-h host` (the deprecated remote-host option), so
`curl … | sudo -h host bash` parked the matcher on the host name and
produced no finding — the same miss shape this class exists to prevent.
Add `h`, note that the class is hand-maintained, and pin every letter of
it with a contract test so a dropped letter fails instead of regressing
to a silent miss.
Also build the repeated-option payload in the linearity regression from
the module constant rather than a second inline copy, so the byte-count
pin and the subprocess exercise the same string.
---------
Co-authored-by: sxh313 <sxh313@users.noreply.github.com>