Skip to content

v2.12.0

Choose a tag to compare

@github-actions github-actions released this 24 Sep 23:18
· 26 commits to main since this release
a297c73

Security

  • Fixes GHSA-qmx6-47vm-3vf7 (high): a binary the classifier did not recognise could carry an elevated command through as safe.

Minor Changes

  • #232 adc0980 Thanks @tufantunc! - A command handed to a binary this classifier does not recognise could carry an elevated command through as safe — the one class that runs on run-command with no approval prompt, whatever the role or approval policy. That gap is now closed: an operand of an unrecognised binary that nothing more specific has already read is classified as a command in its own right, so an elevation it carries is found and the command classifies privileged like any other.

    This does mean a command that used to run silently can now prompt for approval or be refused outright under a profile that does not grant privileged. The one case worth knowing about ahead of time: classification looks at the first word of an operand, so git commit -m "sudo fix the thing" now classifies privileged and needs approval, where git commit -m "fix the sudo thing" still classifies as it always did. If a run-command you relied on starts asking for approval, check whether a commit message, comment, or similar free-text argument happens to start with sudo, doas, pkexec, or su.

    The interpreter table also gains osascript, lua, Rscript, bun, tclsh, deno eval, and pwsh/powershell, so a program handed to one of them now classifies the same way a program handed to python3 -c or node -e already did. pwsh -EncodedCommand's base64 payload is decoded so what it carries is classified rather than merely counted as opaque.

    tclsh carries no -c entry: a differential fuzz run against this branch found that tclsh -c 'exec systemctl stop nginx' had been classifying destructive on the strength of a -c flag real tclsh does not have — it takes a script file or reads one from stdin, the same as every other interpreter in the table without an inline-program flag. That invocation now classifies safe, correctly: tclsh is still a recognised, unreadable interpreter, so echo … | tclsh (the genuine carrier, a program on stdin) still classifies destructive.

    One gap this does not close, so you know where the edge is: an interpreter's own
    value-taking option can still sit between it and its program flag —
    bash -o pipefail -c 'shutdown -h now', python3 -W ignore -c '…' — and that payload
    reaches the unconditional denylist scan only for the canonical sh -c '…' spelling. Such a
    command still classifies destructive, so it is refused for any role that does not hold
    that class and prompts for one that does; what it does not get is the never-allowed
    treatment. This is unchanged from previous releases.

    Reported by @MartOcd1709.

  • #232 adc0980 Thanks @tufantunc! - sort --compress-program=<path> no longer classifies read-only.

    GNU sort runs that program for every temporary file it spills, so a reader becomes a launcher. sort is on the read-only allowlist, so the whole command classified read-only — the one class a readOnly profile permits — and a viewer could run an arbitrary program through read-command while running that same program directly was refused.

    It now classifies destructive, through DISQUALIFYING_ARGS, the table that already held find's -exec family for the same reason. Ordinary sorting is unaffected: sort -u, sort -k2 -n, sort --reverse and a filename that merely contains the word all stay read-only.

    The first version of this fix closed the four exact spellings it was written against (-o, --output and --compress-program, joined and separate) and left GNU sort's own option grammar open around them. Two escapes, both closed now:

    • A short-option cluster is scanned left to right, and GNU sort lets any of its own argument-less short flags sit ahead of -o without consuming it — sort -mo out in writes out exactly as sort -o out in does. -m (merge) was the one argument-less flag missing from that set.
    • getopt_long resolves a -- word by unambiguous-prefix matching, not exact spelling: --o, --ou, --out, --outp and --outpu all mean --output, and --co through --compress-progra all mean --compress-program. --c alone is excluded on purpose — it names both --check and --compress-program, so real sort refuses to run rather than guess.

    Every short flag and every long-option prefix is derived from sort --help and measured against the real binary. sort -tofile, sort -t: -k2,2n, sort -ko/-So/-To and sort --c=… are unaffected: each hands its value to a flag other than -o, or (for the ambiguous --c) never runs at all.