This release closes three command-analysis gaps where a destructive command could be hidden from the gate, and removes a false positive that denied plain git network commands for anyone whose shell exports an SSH override.
Highlights
- Fixed heredoc handling so a carriage-return-suffixed delimiter line can no longer end a heredoc early and let the rest of its body run unanalyzed. (#115)
- Stopped denying
git fetch,git pull, andgit pushwithgit.ssh-envwhenGIT_SSH_COMMAND,GIT_SSH, orGIT_SSH_VARIANTis inherited from the user's shell profile. Inline assignments such asGIT_SSH_COMMAND=./evil git fetchand-c core.sshCommand=...overrides still deny. (#119)
Changed
- GNU Parallel forms the analyzer cannot follow now deny as
parallel.command-stream-dynamic: multiple:::groups, negative{-n}placeholders, and--workdir/--wd. The child command is still expanded and re-rooted, so a catastrophic root or home deletion is still caught when the stream rule is off. (#121) - A placeholder that lands in a position owned by a configured rule's command is now treated as dynamic input and denies with the existing
xargs.shell-dynamicandparallel.shell-dynamicids. (#121) - Improved GNU Parallel job expansion to charge the shared analysis budget as it builds, so a wide
:::product fails closed promptly instead of constructing a very large job matrix before the denial. (#121) - Changed
--workdirtilde handling so only a leading~expands and a tilde inside a path component is literal, as the shell treats it. This also fixes workdir re-rooting on Windows paths containing 8.3 short names such asC:\Users\RUNNER~1\.... (#121) - An override with an unknown rule id and a value other than
onoroffnow reports one diagnostic instead of two. (#120) rule init --examplenow writes the project-scope description and author into the example rulebook instead of the user-scope wording. (#121)
Fixed
- Fixed policy-target comparison on macOS, where a hard link to a policy file could make two lookups of the same path disagree and flip a verdict. Targets are now canonicalized through their parent directory; hard links remain distinct targets. (#117)
Removed
- Removed
shadowedRulesfromdoctor --json; its only value was an empty array. (#121) - Removed
isOverriddenToNonTempfrom thetmpdir-checkstep ofexplain --json; it was the negation of theallowTmpdirVarvalue next to it. (#120) - Removed the accepted-but-ignored
rule --checkflag;cc-safety-net rule --checknow reports an unknown option. (#121)
Security
- A heredoc body now ends only at a byte-exact delimiter line, matching bash. A heredoc written with CRLF no longer closes at a bare delimiter line, so a payload such as
$(rm -rf /)placed after one is analyzed instead of allowed; at strict safety an unterminated heredoc fails closed. (#115) - Brace expansion at command position now uses the quote-aware scanner, so
{"rm",ls} -rf /,{'rm',ls} -rf /, and{r\m,ls} -rf /denyrm.recursive-force-root-or-homeinstead of parsing a literal command head. (#120) - The secret walk of
bash -cnow resolves the command operand through the shell's own option grammar, sobash -c -- "cat .env"and the-xand-svariants are checked for secret access, and an option value such asbash -O .env -c ...is no longer re-read as the command. (#120)