github Dicklesworthstone/destructive_command_guard v0.15.2

3 hours ago

Security fix release. v0.15.1 can fail open under load. Please upgrade.

On a busy machine the v0.15.1 hook could exit without printing a verdict for some destructive commands. Every agent reads a hook that exits silently as "allow", so those commands ran. With about sixteen hook processes running at once, 3-9% of requests for commands such as watch 'git reset' --hard (commands that only dcg's embedded-script reader can judge) were let through this way. Run one at a time, the same commands were always denied. In v0.15.2 a check that runs out of time is retried with the time the hook has left, and if it still cannot finish the answer is ask (or deny under unverified_decision = "deny"), never a silent allow.

OpenCode and Oh My Pi users: refresh the plugin or bridge after upgrading. Both now block a command when dcg crashes, is killed or exits without a verdict. That change is in the generated plugin/bridge file, so an existing file keeps the old fail-open behaviour until it is rewritten:

  • dcg update rewrites it for you when its installer detects the agent, unless you pass --no-configure.
  • Otherwise run dcg install --opencode --force or dcg install --omp --force (add --project for a project-scoped Oh My Pi bridge).
  • DCG_BRIDGE_CRASH_DECISION=allow keeps the old fail-open behaviour for crashes. A dcg that cannot be started at all still fails open, unless DCG_UNVERIFIED_DECISION=deny is set.

Fixed in the fail-open path

  • Silent exit under load (18be8e9). The embedded-code extractor's 50 ms budget ran out on a busy machine, its fallback found nothing, and the unread script was treated as quoted data. A timed-out extraction or AST match is now read again within the hook's deadline; a body that still cannot be read is unverified, not clean.
  • A panic in the hook let the command through (18be8e9). Release builds abort on panic, which agents treat as a non-blocking error. In hook mode a panic now writes the ask/deny answer for the request's protocol before exiting.
  • Binary-looking command text skipped the embedded-code checks (18be8e9). A NUL byte or a run of control characters could hide watch 'git reset' --hard. Such input is now denied under the incomplete-analysis rule, which can be allowlisted after review.
  • [confidence] enabled = true crashed the hook on some wrapped commands (18be8e9), and scored some matches against unrelated text (42414a6), which could downgrade a deny to a warning. A span that does not address the command now keeps the deny.
  • The OpenCode plugin and the Oh My Pi bridge allowed a command when dcg crashed or gave no verdict (8fa6aeb). See the refresh note above.
  • The hook crashed on very deeply nested input (929cce8), which agents also treat as allow. The parse-tree walks no longer recurse.

Other changes

  • Fewer false denials for notes written through an unquoted heredoc (<<EOF). When dcg can prove the output only lands in a plain file, on the terminal or in read-only text tools, only the parts the shell runs while reading the body are checked.
  • New denials for heredoc bodies fed to something that runs them (a shell, ssh, sudo sh, docker exec … sh, at, eval), with either delimiter, and for more disguised spellings: brace-expanded command words, trap/PROMPT_COMMAND/PS*/BASH_ENV commands, escaped or assembled program names, quoted options, relative writes after cd /, and cmd.exe caret escapes when the line also holds unrelated keywords (#499, #500). A workflow that relied on one of these spellings will now be denied.
  • DCG_LOG=<filter> prints hook-mode tracing to stderr.

Full detail: CHANGELOG.md.

Assets

Six archives, each holding only the dcg binary (dcg.exe on Windows): x86_64-unknown-linux-musl (static), aarch64-unknown-linux-gnu (glibc 2.28 or newer), x86_64-apple-darwin, aarch64-apple-darwin, x86_64-pc-windows-msvc, aarch64-pc-windows-msvc. Every archive and both installers have a .sha256, a minisign signature (key 69B3955C8D2E62A8, the key pinned in install.sh, install.ps1 and release/minisign.pub) and a key-based Sigstore bundle (.sigstore.json, the installers' pinned cosign key). SHA256SUMS is signed with the same minisign key. Built on self-hosted machines with the dsr release process; GitHub Actions were not used.

The Windows binaries in this release were cross-compiled on macOS with cargo-xwin (MSVC targets) because the native Windows build hosts were unreachable. The Windows-specific code was compiled for Windows, but the native PowerShell end-to-end suite was not run for this release.

V=v0.15.2; T=aarch64-apple-darwin   # or x86_64-unknown-linux-musl, etc.
curl -fLO "https://github.com/Dicklesworthstone/destructive_command_guard/releases/download/$V/dcg-$T.tar.xz"
curl -fLO "https://github.com/Dicklesworthstone/destructive_command_guard/releases/download/$V/dcg-$T.tar.xz.minisig"
minisign -Vm "dcg-$T.tar.xz" -P RWSoYi6NXJWzaRs1mJmOwwXrZfPWcq6MXnQlNMLBYKzlIQTLwuVQG6uO

Don't miss a new destructive_command_guard release

NewReleases is sending notifications on new releases.