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 updaterewrites it for you when its installer detects the agent, unless you pass--no-configure.- Otherwise run
dcg install --opencode --forceordcg install --omp --force(add--projectfor a project-scoped Oh My Pi bridge). DCG_BRIDGE_CRASH_DECISION=allowkeeps the old fail-open behaviour for crashes. A dcg that cannot be started at all still fails open, unlessDCG_UNVERIFIED_DECISION=denyis 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 = truecrashed 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_ENVcommands, escaped or assembled program names, quoted options, relative writes aftercd /, 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