# Changelog All notable changes to **dcg** (Destructive Command Guard) are documented here. Versions marked **[Release]** have published GitHub Releases with pre-built binaries. Versions marked **[Pre-release]** are GitHub prereleases that were not promoted to latest. Versions marked **[Tag]** are git tags only (no binaries published). Repository: --- ## [v0.6.8](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.6.8) -- 2026-07-15 [Release] Windows installer correctness hotfix that completes the real-host ConstrainedLanguage path begun in v0.6.7. ### Fixed - **Make the mandatory installed-version assertion and optional `-Verify` self-test work in Windows PowerShell 5.1 ConstrainedLanguage (#194).** The installer now captures native `dcg --version` and `dcg test` output under a narrowly scoped non-terminating error preference, restores the caller's preference, and judges each probe by its documented process exit code. This preserves strict error handling while preventing DCG's intentional human diagnostics on stderr from being promoted to a terminating `NativeCommandError` under the installer's script-wide `$ErrorActionPreference = 'Stop'`. - Extend the Windows PowerShell 5.1 forced-ConstrainedLanguage integration test with native commands that exercise successful version capture, a failing version probe, and both allow/deny self-test outcomes while emitting diagnostics on stderr. The regression now covers the exact stream behavior that v0.6.7's function-level installer tests missed. - Advance the composite GitHub Action examples and its transient API-failure fallback to v0.6.8 so an unavailable latest-release endpoint cannot select the superseded installer. - Make the real Codex E2E harness explicitly trust its freshly generated, hermetic DCG hook for automation. Codex 0.144.x otherwise skips untrusted one-shot hook paths, which made the harness run destructive fixture commands without exercising DCG even though direct protocol tests passed. The harness now pins both `HOME` and `CODEX_HOME` to that generated configuration, accepts hook-status markers only from Codex stderr, and aborts before issuing any destructive prompt unless the initial safe-command trust handshake succeeds. - Refresh the scan regression golden for the six legitimate PostgreSQL and Docker findings now emitted by the current default packs. The harness now compares the complete normalized deterministic scan contract rather than only counts and a sorted rule-ID multiset. - Make the shell E2E suite use the same generous test-only hook deadline as the Rust E2E helpers. Functional rule assertions are now deterministic under scheduler pressure while the dedicated performance tests continue to enforce the production 200 ms fail-open budget. ### Dependencies - Update `toml` to 1.1.3, `toml_edit` to 0.25.13, and `toml_writer` to 1.1.2 for the upstream writer-overflow fix. Update the dev-only `which` dependency to 8.0.5. The root lock uses the independently resolved minimal four-package update and excludes PR #208's unrelated edge rebindings. The previously stale fuzz lock is refreshed from its v0.4.5-era graph and aligned to the gated root dependency versions so full locked fuzz metadata succeeds. ### Release integrity - Rebuild and test all six binaries manually outside GitHub Actions, with SHA-256 checksums, minisign signatures, signed DSR SLSA provenance, a source-tree SPDX SBOM, and real installer verification on Linux, macOS, and Windows PowerShell 5.1. ## [v0.6.7](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.6.7) -- 2026-07-14 [Release] Security and correctness release with Windows-policy compatibility groundwork. This closes the stdin-driven database-client bypass class, blocks force-refspec pushes, repairs project allowlists outside Git repositories, fixes two command-line false positives, and adds the checksum, signature, archive, and encoding primitives needed by the Windows installer under WDAC/AppLocker ConstrainedLanguage. Its final PowerShell 5.1 native-output captures are corrected in v0.6.8. ### Security - **Trace indirect input into protected database clients (#191).** Bounded literal `echo`/`printf` and single-file `cat` pipelines, grouped/subshell consumers, redirects (including prefix and inherited `exec` forms), heredocs, Redis `--pipe`, and command substitutions are reconstructed and evaluated against the consumer pack for Redis-compatible clients, PostgreSQL, MySQL/MariaDB, MongoDB, and SQLite. Unknown or dynamic producers, unsafe files, invalid encodings, and oversized payloads fail closed under the stable `:stdin-unverified` rule. File inspection rejects symlinks and special files and uses nonblocking/no-follow opens on Unix. Multi-command producers cannot masquerade as one literal producer. - **Parse kubectl dry-run semantics instead of guessing with regex.** `kubectl delete -f -` is blocked unless the final effective `--dry-run` value is provably bare/client/server/true. Repeated, separated, quoted, escaped, dynamic, and post-`--` arguments follow pflag ordering without a safe-then-unsafe override bypass. - **Block Git's leading-plus force refspec syntax in strict mode (#202).** Arbitrary `+` pushes now hit `push-force-any`, including quoted, escaped, ANSI-C-quoted, direct `+main`/`+master`, and `+HEAD:refs/heads/main` forms. Brace/glob/dynamic refspecs fail closed, and `git push --mirror` is explicitly blocked because it force-updates and deletes remote refs. - **Evaluate GNU sed shell-execution programs semantically.** Inert substitutions remain maskable data, while the `e` command and `s///e` flag feed their literal shell command back through the normal evaluator. Input-dependent executable replacements fail closed under `core.filesystem:sed-exec-unverified`; sandboxed sed invocations remain allowed only when `--sandbox` is an active option rather than an operand after `--`. `-f` programs are inspected with option arity respected, while compound-command program files fail closed against mutation races. - **Remove attacker-controlled temp-root whitelists.** Only static paths under literal `/tmp` and `/var/tmp` qualify for automatic POSIX safety; `$TMPDIR`, `${TMPDIR:-...}`, substitutions, escaped traversal, and dynamic suffixes require review. The same fail-closed rule covers redirects and moves. Absolute `truncate` sizes now block because they may shrink at runtime, and only the final effective `dd of=` operand determines safety. Windows recursive-delete temp whitelisting was removed because ambient `%TEMP%` and multi-target commands could otherwise shadow a destructive target. ### Fixed - **Make project allowlists effective outside Git repositories (#199).** The repository root remains authoritative inside Git. Elsewhere, the nearest ancestor containing `.dcg/allowlist.toml` governs nested directories, and a new scope starts in the current directory when no such ancestor exists. Read, list, and write operations now share that resolver. - **Allow literal double-quoted `/tmp/` and `/var/tmp/` recursive deletes (#201).** Quoted paths now have parity with their unquoted equivalents while traversal, expansion, brace, quote-concatenation, and escape tricks remain blocked. - **Stop inert sed substitutions from looking like shell redirects (#198).** Only a single non-executing, non-writing substitution is masked; arbitrary sed programs, `e`, `s///e`, and `s///w` remain visible to the guard. - **Treat `n` as false for display/mode environment flags (#203).** `DCG_NO_COLOR=n`, `DCG_ROBOT=n`, and related flags now match the documented boolean parser. - Thread the active hook deadline through the final pack-evaluation pass instead of accidentally dropping it. ### Windows installer - **Support WDAC/AppLocker ConstrainedLanguage installs and updates (#194).** The installer falls back from `Get-FileHash` to signed inbox `certutil.exe`, uses trusted `tar.exe` for zip inspection/extraction, emits UTF-8 without a BOM using primitive operations, and avoids blocked .NET helpers for URL, PATH, architecture, and configuration handling. Real-host release validation subsequently found that the final `dcg --version` capture and optional `-Verify` self-test still tripped PowerShell 5.1's native-stderr promotion under `$ErrorActionPreference = 'Stop'`; v0.6.8 fixes both native capture paths. ### Release integrity - **Authenticate manually published artifacts with a long-lived minisign trust root.** Both installers verify an adjacent `.minisig` when the external `minisign` executable is available, always abort on an invalid signature, and offer `--require-minisign` / `-RequireMinisign` for fail-closed installs. Offline artifact/signature URL overrides are covered by the installer test suites. Version selection now requires an exact SemVer tag, downloaded archives must contain exactly one root-level binary, and installer self-tests prove that the installed binary reports the requested version. - The six-platform release is built outside GitHub Actions, packaged reproducibly, checksummed, signed with DSR's minisign key, and accompanied by an SPDX SBOM plus signed SLSA provenance statements. Sigstore bundles are not claimed for these manual builds because no Actions OIDC identity is involved. ### Dependencies - Upgrade FrankenSQLite to 0.1.16 (including atomic commit-marker recovery), `self_update` to 1.0.0-rc.5, and the current compatible regex/memchr stack. `cargo audit` reports no known dependency vulnerabilities; cargo-deny's advisory, bans, and source checks also pass (the repository does not yet define a license-policy configuration). ## [v0.6.6](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.6.6) -- 2026-07-13 [Release] Security and correctness release. Closes a critical, attacker-triggerable guard-bypass (an exponential-time hang in command-substitution preprocessing), enforces path-scoped allowlists across every evaluation entrypoint, lands hook-protocol correctness fixes for Codex, GitHub Copilot CLI, and VS Code Copilot Chat, and adds heredoc/pack false-positive fixes plus a dependency refresh. ### Security - **Fix an exponential-time hang in command-substitution preprocessing that let a destructive command bypass the guard (#189).** A ~90-byte payload of a destructive command followed by ~30 unterminated `$(` drove `split_command_segments` into 2^n re-scans, hanging `dcg` far past its 200 ms hook budget; because agents fail open on a hung hook, the destructive command then executed. The command-substitution scanners now propagate an unterminated nested construct instead of rescanning the suffix per opener (2^n → linear, output-equivalent on well-formed input), and the matching blowup in the `$((` arithmetic/command-substitution disambiguation is closed too. `$(`, `<(`, `>(`, and `$((` openers are all bounded; a payload that previously hung now blocks in well under a millisecond. - **Enforce path-scoped allowlists across all evaluation entrypoints (#186).** `paths = [...]` allowlist entries were silently applied globally whenever no heredoc content-allowlist project was configured, because the shared project path resolved to `None` and path-aware matchers skip path checks on `None`. The explicit working directory is now authoritative regardless of heredoc config, and the hook, `dcg test`, `dcg hook --batch`, and `dcg classify` all thread the real cwd; the heredoc-AST allowlist branches use the path-scoped matcher. ### Fixed - **Restore enforcement on Codex CLI 0.144.x for native Windows (#183).** Codex denials now use its accepted minimal three-field `hookSpecificOutput` JSON with exit code 0. The previous exit-code-2 contract is collapsed to exit 1 by Codex's PowerShell wrapper, which Codex classifies as hook failure and then fails open. The new response is strict-parser-safe and retains the full operator explanation on stderr. - **Honor GitHub Copilot CLI's native camelCase `preToolUse` protocol (#182).** Copilot responses now contain exactly its documented top-level `permissionDecision` and `permissionDecisionReason` fields, without legacy control or dcg-only metadata that caused the decision to be discarded. Unix and PowerShell installers now write a user-level hook under `${COPILOT_HOME:-~/.copilot}/hooks`, protecting every workspace; uninstallers remove that hook while preserving coexisting entries and also clean the legacy repo-local hook when present. - **Protect VS Code Copilot Chat terminal tools (#184).** `runTerminalCommand`, `run_in_terminal`, and `runInTerminal` now route through the Claude-compatible deny protocol and read `tool_input.command`, covering both the documented and observed VS Code payload names. - **Treat `spx session handoff` heredocs as structured stdin data (#181).** The narrowly-scoped, line-bounded sink masks handoff prose without masking other `spx` subcommands or commands after the heredoc terminator. - **Stop inert prose in quoted no-op-builtin heredocs from tripping git/ filesystem rules (#181).** `true <<'EOF' … EOF` and `: <<'EOF' … EOF` (the shell block-comment idiom) now have their bodies masked as data — but only for quoted delimiters, which suppress expansion. An unquoted delimiter still expands command substitutions, so those keep flowing through pack matching (no false negative), and commands after the terminator are unaffected. - **Render pack styling and separate the legend in `dcg packs` (#187, #188).** Styled tree labels are parsed through `rich_rust`'s markup renderer instead of being emitted as literal `[bold]`/`[dim]`/`[green]` tags; unstyled labels keep literal brackets. The legend and config hint move out of the tree hierarchy into a footer beneath it. - **Correct the dcg skill's missing-binary install guidance (#185).** All five managed skill copies now point to this repository and the working easy-mode installer instead of the nonexistent `anthropics/destructive-command-guard` URL; the public skill manifest checksum was refreshed and validated. - **Keep catastrophic JavaScript deletes blocking under contention.** A lexer-aware pre-AST backstop catches literal `fs.rmSync()` calls targeting catastrophic paths before the bounded AST worker can fail open, while ignoring comments, template text, and non-catastrophic targets. ### Security and maintenance - Upgrade `self_update` to `1.0.0-rc.4` and narrow `rich_rust` to the Markdown feature, removing the obsolete syntax-parser dependency stack while retaining dcg's purpose-built regex highlighter. `cargo audit` reports no known vulnerabilities. - Make AST-heavy protocol tests deterministic on saturated CI hosts without changing the production 20 ms fail-open ceiling, and expand the platform backtracking audit plus PowerShell/batch extractor documentation sentinels. ### Documentation - **Correct the modular-pack docs (#187, #190).** README, `docs/agents.md`, and `docs/configuration.md` now use real pack/category IDs and document that a category ID (e.g. `database`) expands to all its sub-packs, including in agent-profile `extra_packs`/`disabled_packs`; the bogus `extra_packs = ["paranoid"]` / `["core","database","filesystem"]` examples are replaced, and `"paranoid"` is clarified as a graduation mode, not a pack. - **Document the stdin/pipe/redirection REPL bypass as a known limitation (#191).** A destructive payload reaching a stdin-driven REPL binary (`redis-cli`/`psql`/`mysql`/`mongosh`/`sqlite3`) via a pipe, `<` redirection, or command substitution used as an argument is not yet traced (direct args and here-strings are still blocked); a data-flow-aware fix is tracked separately. ## [v0.6.5](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.6.5) -- 2026-07-02 [Release] Security re-release of v0.6.4 with correct per-architecture binaries. No code changes from v0.6.4 — this exists solely to publish a correctly-packaged release through the CI pipeline. ### Fixed - **Cross-architecture release binaries are now built for the correct target (#174).** The `v0.6.4` `dist` build installed the cross-target std against the floating `@nightly` toolchain instead of the `nightly-2026-06-06` pinned in `rust-toolchain.toml`, so the two cross-std targets (`x86_64-unknown-linux-musl`, `aarch64-pc-windows-msvc`) failed to build with `error[E0463]: can't find crate for core`. Because `release` needs `build`, that skipped the GitHub-Actions publish and forced an out-of-band fallback that shipped **wrong-arch binaries**: the `aarch64-unknown-linux-gnu` tarball carried an x86-64 ELF and the `x86_64-apple-darwin` tarball carried an arm64 Mach-O. On `aarch64` Linux the installed guard could not execute (`Exec format error`), and because Claude Code hooks are fail-open by design, the guard was silently dead while appearing installed — every destructive command was permitted with no visible error. The toolchain install now pins `nightly-2026-06-06` and adds the target std to it, so all six targets build on native runners and publish through CI. Explicit per-target arch-verify gates (`file` / `objdump -T`) already guard against a recurrence. ## [v0.6.4](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.6.4) -- 2026-06-27 [Release] Toolchain-pin release; superseded by v0.6.5 (its cross-arch tarballs were mispackaged — see #174 above). ### Changed - **Pin the toolchain to `nightly-2026-06-06`.** Bare `nightly` could no longer compile `rustix 1.1.4`, which had shipped v0.6.3 as Windows-only and broke fresh installs on newer distros. Restores the full platform set and bundles the 18-issue CLI/hook audit, the #160 fail-closed hardening (BOM-strip + opt-in `DCG_FAIL_CLOSED` + protocol-aware denial + oversized-input handling), and #151/#150/#155. ## [v0.6.3](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.6.3) -- 2026-06-25 [Release] Patch release for Windows command normalization coverage. ### Fixed - **Block wrapper flag-value command substitutions.** `env` and `sudo` wrapper normalization no longer strips option values that contain command/process substitutions, preserving destructive payloads for detection. - **Normalize quoted Windows binary paths with backslashes.** Quoted paths such as `"C:\Program Files\Git\bin\git.exe" reset --hard` now normalize to the `git` command instead of being mangled by escape handling. - **Tighten quick-reject keyword coverage.** Windows uppercase destructive aliases and Redis-compatible `valkey-cli` / `keydb-cli` commands now reach the destructive pattern matchers instead of being skipped by the fast path. ## [v0.6.2](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.6.2) -- 2026-06-25 [Release] Patch release for the native-Windows installer. ### Fixed - **Fix checksum resolution on Windows PowerShell 5.1.** GitHub release sidecars such as `dcg-x86_64-pc-windows-msvc.zip.sha256` can be returned by `Invoke-WebRequest` as `byte[]` when uploaded as octet-stream assets. The installer now decodes byte-array checksum content as UTF-8 before parsing, so the pinned one-liner verifies and installs the Windows zip correctly. ## [v0.6.1](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.6.1) -- 2026-06-25 [Release] Patch release candidate for the native-Windows launch, superseding the unpublished `v0.6.0` tag. ### Fixed - **Close an inline-script extraction under-block.** Interpreter wrapper flags whose values are not simple barewords (`python -W ignore::... -c`, `node --max-old-space-size 4096 -e`, `bash --rcfile /path -c`, PowerShell `-Version 5.1 -Command`, and attached Perl flags like `-MFile::Spec`) are now skipped correctly before extracting the dangerous inline script payload. - **Refresh Windows release docs.** README and `docs/windows.md` now describe Windows x64 + ARM64 artifacts, the ARM64-to-x64 fallback for older releases, the Windows Cursor PowerShell bridge, and the full PowerShell uninstall hook coverage. ## [v0.6.0](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.6.0) -- 2026-06-24 [Tag] Native Windows support, PowerShell installer automation, Windows release artifacts, heredoc data-sink masking for `git` stdin targets, plus a soundness fix to heredoc target resolution. ### Added - **Native-Windows destructive-command protection.** New `windows.filesystem` and `windows.system` packs are **on by default on Windows** — blocking cmd `del /s`, `rd /s`, `format :`, PowerShell `Remove-Item -Recurse -Force` (and aliases), `Clear-Content`/`Clear-RecycleBin`, plus `vssadmin delete shadows` / `wmic shadowcopy delete` (Volume Shadow Copy destruction), `diskpart`, `Format-Volume`, `Clear-Disk`, `cipher /w`, and `bcdedit /delete`. Opt-in `windows.misc` (`reg delete`, `net user /delete`, `wsl --unregister`, `robocopy /MIR`) and `windows.powershell` (registry/provider deletes, `Remove-LocalUser`, `Disable-ComputerRestore`, `Remove-VM`, …) packs round out coverage. All patterns are case-insensitive. - **Windows-aware engine + scan.** Command normalization handles drive-letter paths (`C:\Windows\System32\del.exe`) and case-insensitive verbs; `dcg scan` now extracts commands from PowerShell (`.ps1`/`.psm1`/`.psd1`) and batch (`.cmd`/`.bat`) scripts. - **Windows install one-liner + docs.** README gains the PowerShell `& ([scriptblock]::Create((irm ".../install.ps1"))) -EasyMode -Verify` installer; new [`docs/windows.md`](docs/windows.md) documents Windows behavior, paths (`%ProgramData%\dcg` system layer), and limitations. - **Windows CI.** A `check (windows)` job (clippy + full test suite on `windows-latest`, nightly/MSVC) now guards against Windows regressions. ### Fixed - **Stop false positives on `git` commit/object messages read from stdin (#136, data-sink half).** `git commit -F -`, `git commit --file=-` / `--file -` / `-F-`, and `git hash-object --stdin` consume the heredoc body as *data* (a commit/tag/note message or object content) that git never executes as shell. Their heredoc body is now masked out of the raw-shell rescan exactly like `cat`/`tee` (#109), so a commit message that merely contains "restore" or "reset --hard" no longer trips the `core.git:*` rules. The unsound interpreter-stdin case (`python3 -`/`node -`, whose body *is* executed) remains deliberately unmasked. - **Soundness: heredoc target resolution is now bounded to the heredoc's own physical line.** `tokenize_backwards` does not treat newlines as command boundaries, so an unbounded backward scan could resolve a data-sink target (or the new git stdin sentinel) from an *earlier* line and mask a *later*, genuinely-executing heredoc body — e.g. `cat f\nbash <` rebuild pattern collided on re-insert of the same rowid. Fixed upstream in [frankensqlite#94](https://github.com/Dicklesworthstone/frankensqlite/issues/94) (commit `a0425adb` — live virtual-table DELETE now routes through the module's per-row `xUpdate` delete, matching SQLite). dcg pins that fix via a git rev of `fsqlite`/`fsqlite-types`/`fsqlite-error`. The three previously-failing `history::schema` FTS tests now pass. ### Packaging note - This release is distributed as **GitHub-release binaries** (the primary install path). Because it pins FrankenSQLite to a git revision pending an `fsqlite` crates.io release, **v0.5.5 is not published to crates.io**; the registry stays at v0.5.4 for the guard feature (the FTS-rebuild fix lands there once `fsqlite` publishes the fix). --- ## [v0.5.4](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.5.4) -- 2026-05-25 [crates.io only — no GitHub binaries] Published to **crates.io** (first registry publish of the 0.5.x line since v0.4.5), but the GitHub-release binaries did **not** ship: the `dist` run was blocked first by `cargo fmt`/clippy and then by the FrankenSQLite FTS5 bug above. GitHub binaries resume at v0.5.5. First successful release and crates.io publish of the 0.5.x line since v0.4.5: v0.5.0–v0.5.2 were cut as GitHub releases but never published to the registry, and v0.5.3's `dist` run failed at `cargo fmt --check`, so it shipped nothing. v0.5.4 carries the v0.5.3 fixes forward and adds the items below. Closes [#126](https://github.com/Dicklesworthstone/destructive_command_guard/issues/126). ### Codex on Windows - **dcg now descends into `powershell -Command` / `pwsh -c` inline scripts** ([#125](https://github.com/Dicklesworthstone/destructive_command_guard/issues/125)). Codex on Windows executes shell commands via `powershell.exe -Command ''`. dcg previously unwrapped only `bash -c` / `sh -c`, so a destructive command inside the PowerShell wrapper reached the shell unevaluated. The inline-script extractor now unwraps `powershell` / `pwsh` — including the quoted full-path `"C:\…\powershell.exe" -Command '…'` form and the `-c` abbreviation — and re-evaluates the inner command against every pack. Note: whether Codex on Windows actually *fires* the PreToolUse hook for its `command_execution` event is Codex-side behavior; this change guarantees that once a wrapped command reaches dcg, it is caught. - **`uninstall.ps1` also writes `hooks.json` as UTF-8 without a BOM**, matching the `install.ps1` fix; both installer and uninstaller now preserve array-ness when reading an existing hook config. ### Installer - **`install.sh` installs shell completions for the invoking user, not root, when run under `sudo`** — completions land in the caller's config directories. ### Tests - Added an end-to-end regression test for the [#124](https://github.com/Dicklesworthstone/destructive_command_guard/issues/124) multi-line `git commit -m "…git push --force…"` body case, and dropped an overclaimed pack-level assertion that cannot hold at the raw-regex layer (documented inline) — the multi-line body is defended by `-m` masking in the full `evaluate_command` pipeline, not by `pack.check()`. ### Packaging - Slimmed the published crate via `exclude` (drops `.ntm/`, `*.png`, `*.webp`, `agent_baseline/`, `action/`). Source and binary are unaffected. --- ## [v0.5.3](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.5.3) -- 2026-05-23 [Tag] ### Pattern false-positive fixes - **`push-force-{long,short}` no longer fires across shell-token boundaries** ([#124](https://github.com/Dicklesworthstone/destructive_command_guard/issues/124)). The walker `(?:\S+\s+)*` between `git`/`push` and the force flag matched `\S` greedily, which includes shell metacharacters (`&;|`()<>` plus backticks). That meant `git commit -m "...git push --force..."`, here-doc bodies, `&&`-chained `echo` lines, and `git log --grep='git push --force'` all tripped the Critical rule — and dcg refused the entire command. Switched both regexes to the bounded form already used by `branch-force-delete` since [#121](https://github.com/Dicklesworthstone/destructive_command_guard/issues/121): `(?:[^\s&;|`()<>]+\s+)*`. Added five regression cases covering the shell-boundary scenarios. ### Codex on Windows - **`install.ps1` now writes `hooks.json` as UTF-8 without the BOM** ([#125](https://github.com/Dicklesworthstone/destructive_command_guard/issues/125)). The previous `Set-Content -Encoding UTF8` on Windows PowerShell 5.1 (the default on Win10/Win11) prepended a UTF-8 BOM that Codex Desktop rejected with `expected value at line 1 column 1`. The hook installed cleanly, appeared in the Codex UI, and silently did nothing. Switched both write paths to `[System.IO.File]::WriteAllText` with `System.Text.UTF8Encoding $false` — works identically on PS 5.1 and PS 6/7+ without the PS6-only `-Encoding UTF8NoBOM`. ### crates.io - **Intended as the first crates.io publish since v0.4.5 — but the `dist` run for v0.5.3 failed at `cargo fmt --check`, so no binaries or crate were published.** Superseded by v0.5.4, which completes the publish ([#126](https://github.com/Dicklesworthstone/destructive_command_guard/issues/126)). --- ## [Unreleased] (after v0.5.1) ### Agent support - **Grok (xAI) protocol added as a first-class agent and hook target.** dcg now detects Grok CLI / Grok Build TUI and emits its native JSON wire shape so blocking actually sticks when Grok invokes shell tools. - **Detection.** Grok is recognised by any of three environment variables (`GROK_SESSION_ID`, `GROK_HOOK_EVENT`, `GROK_WORKSPACE_ROOT`) and by parent-process basename (`grok`, `grok-cli`, `grok-build`). The hook protocol is auto-selected when stdin carries `hookEventName: "pre_tool_use"` or `toolName: "run_terminal_cmd"`, with explicit guards so the Hermes (`pre_tool_call`) and Copilot (`event` / `tool_args`) markers still win on their own payloads. - **Wire shape.** Denies emit `{"decision":"deny","reason":"…", …}` on stdout — *not* Hermes' `"block"`. Allows are empty stdout + exit 0. Warns become explicit `{"decision":"allow","reason":"DCG warn: …"}` so Grok logs the advisory without escalating to a block. - **Installer.** `dcg install --grok` writes a self-contained `~/.grok/hooks/dcg.json` (`PreToolUse` / `matcher: "Bash"`, which Grok internally aliases to `run_terminal_cmd`). `--grok --project` writes `/.grok/hooks/dcg.json` for per-repo installs. Grok also picks dcg up via the existing `~/.claude/settings.json` compatibility layer, so users who already ran `dcg install` get protection with no further action. - **Doctor.** `dcg doctor` adds a "Checking Grok hook registration…" line when a `.grok/` directory or `GROK_*` env var is present. `dcg doctor --fix` will write the native hook for you if it's missing. The check is silent on hosts that have never had Grok installed, to avoid noise. - **Tests.** Eight new protocol-detection tests plus full denial/warning JSON-shape assertions in `hook::tests`, three new env detection tests in `agent::env_tests`, and CLI parse coverage for `--grok`/`--grok --project`. Closes the contribution proposals in [#117](https://github.com/Dicklesworthstone/destructive_command_guard/pull/117) and [#118](https://github.com/Dicklesworthstone/destructive_command_guard/pull/118) by reimplementing the feature independently, including the corrected user-level hook path (`~/.grok/hooks/dcg.json`, not `~/.grok/settings.json`) and the correct block keyword (`"deny"`, not `"block"`). ### Release-engineering fixes - **Linux x86_64 now ships as static musl** ([#114](https://github.com/Dicklesworthstone/destructive_command_guard/issues/114)). Previous releases linked against the build runner's glibc and required GLIBC ≥ 2.39 on the host, which blocked Ubuntu 22.04 LTS and any long-support distro. The dist matrix now uses `x86_64-unknown-linux-musl` with the `rustls` feature on `self_update` so OpenSSL isn't dragged in, plus an `objdump -T | grep GLIBC_` post-build check that fails the release if the binary unexpectedly re-acquires glibc symbols. `install.sh` was updated to map `linux-x86_64` to the musl target by default, with a one-shot HEAD-probe fallback to the legacy gnu artifact for older pinned versions so the transition doesn't break users who ask for an older version explicitly. - **aarch64 release artifact verified at build time** ([#112](https://github.com/Dicklesworthstone/destructive_command_guard/issues/112)). v0.5.1's `dcg-aarch64-unknown-linux-gnu.tar.xz` published an x86-64 ELF binary. Native ARM runners in the current matrix make that impossible by construction, but a `file /release/dcg | grep aarch64` post-build check now fails the release if the architecture ever drifts again. ## [v0.5.1](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.5.1) -- 2026-05-03 [Release] Patch release after v0.5.0 covering two false-positive/false-negative classes discovered during a wide review of recent agent-authored fixes: the heredoc parser's handling of the `<<-` / `<<~` markers and a missed-coverage gap in the compact `-XDELETE` / `--request=DELETE` / `--method=DELETE` curl/glab API forms. 5 commits since v0.5.0. ### Heredoc parser hardening (issue #109) - Consumed whitespace between the `<<-` / `<<~` marker and the delimiter so bash-legal forms like `cat <<- 'EOF'` no longer fall through the quoted-delimiter strip and bail out unmasked. Pre-fix the body escaped masking, and pack matching denied prose like "gh repo delete" inside a heredoc fed to a non-executing target ([f3c96bd](https://github.com/Dicklesworthstone/destructive_command_guard/commit/f3c96bd), test coverage added in [a739dc9](https://github.com/Dicklesworthstone/destructive_command_guard/commit/a739dc9) and [03bf276](https://github.com/Dicklesworthstone/destructive_command_guard/commit/03bf276)). - Disambiguated `cat << -EOF` (whitespace before the dash, delimiter is literally `-EOF`) from `cat <<-EOF` (tab-strip marker, delimiter is `EOF`) by gating the marker classification on `skip_whitespace == 0`. Same fix applied to `~` so `cat << ~TILDE` is also a Standard heredoc with delimiter `~TILDE`. Aligned the manual `parse_heredoc_delimiter` path with the regex-based `extract_heredocs` path so both correctly map `~` to `IndentStripped` rather than `TabStripped`. Without this, a `cat <<~EOF` with space-indented body lines and a space-indented terminator was never recognized by the masker, the body escaped masking, and pack matching produced false positives on documentation prose like `rm -rf /` inside the heredoc body ([a8a0a8d](https://github.com/Dicklesworthstone/destructive_command_guard/commit/a8a0a8d)). ### Compact curl / glab API method forms - Closed a false-negative gap where four destructive-pattern regexes still required whitespace between `-X` / `--request` / `--method` and the HTTP verb. Pre-fix bypasses such as `glab api -XDELETE projects/123/variables/SECRET`, `glab api --method=DELETE /projects/123/protected_branches/main`, `curl -XDELETE https://splunk.example.com:8089/services/data/inputs/abc`, and `curl --request=DELETE https://circleci.com/api/v2/.../envvar/FOO` slipped through unblocked because curl and glab's cobra-based CLI accept those compact short forms and equals long forms. Aligned the affected packs with the broader `(?:-X\s*|--request(?:=|\s+))VERB` shape already used by `gh api`, Datadog, PagerDuty, Prometheus, New Relic, Meilisearch, and the email packs, and added regression tests for each block ([1fdfbec](https://github.com/Dicklesworthstone/destructive_command_guard/commit/1fdfbec)). ### Representative commits | Commit | Subject | |--------|---------| | [f3c96bd](https://github.com/Dicklesworthstone/destructive_command_guard/commit/f3c96bd) | fix(heredoc): consume whitespace between `<<-` / `<<~` marker and delimiter (issue #109) | | [a739dc9](https://github.com/Dicklesworthstone/destructive_command_guard/commit/a739dc9) | test(heredoc): cover `<<-` / `<<~` with space-after-marker quoted forms (issue #109) | | [03bf276](https://github.com/Dicklesworthstone/destructive_command_guard/commit/03bf276) | test(heredoc): restore unquoted-delimiter assertion to its parent test | | [a8a0a8d](https://github.com/Dicklesworthstone/destructive_command_guard/commit/a8a0a8d) | fix(heredoc): respect whitespace gap when classifying tab-strip marker | | [1fdfbec](https://github.com/Dicklesworthstone/destructive_command_guard/commit/1fdfbec) | fix(packs): match `curl -XDELETE` and `--request=DELETE` compact forms across CI/platform packs | ## [v0.5.0](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.5.0) -- 2026-05-02 [Release] Minor pre-1.0 release after v0.4.11 for the Codex hardening wave, installer preservation work, Railway/API guard improvements, and the latest safe-pattern bypass fixes. This release covers 75 commits since v0.4.11. ### Codex & Multi-Agent Hook Support - Applied protocol-derived agent profiles, so Codex/Copilot/Gemini/Claude-style hook payloads can select the right agent profile without relying only on process environment detection ([7f7d67e](https://github.com/Dicklesworthstone/destructive_command_guard/commit/7f7d67e)). - Kept blank Codex `turn_id` fields from forcing the Codex stderr-deny path, preserving Claude-compatible JSON behavior for payloads that are not actually Codex hook events ([d0a1bef](https://github.com/Dicklesworthstone/destructive_command_guard/commit/d0a1bef)). - Hardened Copilot handling for PowerShell payloads, missing tool names, and warn-severity decisions so Copilot warnings remain non-stopping while denies still block ([e11baea](https://github.com/Dicklesworthstone/destructive_command_guard/commit/e11baea), [4862be4](https://github.com/Dicklesworthstone/destructive_command_guard/commit/4862be4), [708536e](https://github.com/Dicklesworthstone/destructive_command_guard/commit/708536e)). - Added and expanded subprocess-level Codex protocol coverage, including hermetic HOME isolation, allow-once/allowlist parity, pack enablement, heredoc behavior, and cross-protocol block/allow shape checks ([tests/codex_hook_protocol.rs](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/tests/codex_hook_protocol.rs)). ### Installer & Uninstaller Reliability - Made Unix and Windows installers preserve malformed or user-owned hook configuration instead of overwriting it for Claude Code, Codex CLI, Gemini CLI, GitHub Copilot CLI, Cursor IDE, and PowerShell hook payloads ([c55bf33](https://github.com/Dicklesworthstone/destructive_command_guard/commit/c55bf33), [1a4b015](https://github.com/Dicklesworthstone/destructive_command_guard/commit/1a4b015), [563d538](https://github.com/Dicklesworthstone/destructive_command_guard/commit/563d538), [46f3764](https://github.com/Dicklesworthstone/destructive_command_guard/commit/46f3764), [fba6067](https://github.com/Dicklesworthstone/destructive_command_guard/commit/fba6067)). - Preserved coexisting user hooks while keeping dcg first in the relevant Bash hook lists, including mixed Copilot entries and existing Claude hooks ([792236e](https://github.com/Dicklesworthstone/destructive_command_guard/commit/792236e), [85028ce](https://github.com/Dicklesworthstone/destructive_command_guard/commit/85028ce), [389ac52](https://github.com/Dicklesworthstone/destructive_command_guard/commit/389ac52)). - Rejected empty or flag-shaped installer option values so arguments like `--version --system` fail as setup errors instead of treating `--system` as the version value ([e8cb117](https://github.com/Dicklesworthstone/destructive_command_guard/commit/e8cb117)). - Matched uninstall ownership checks more exactly for Cursor, Codex, PowerShell, and non-dcg hook preservation so uninstallers remove only dcg's own entries ([6d71b68](https://github.com/Dicklesworthstone/destructive_command_guard/commit/6d71b68), [af68c72](https://github.com/Dicklesworthstone/destructive_command_guard/commit/af68c72), [b043068](https://github.com/Dicklesworthstone/destructive_command_guard/commit/b043068), [e8e65d1](https://github.com/Dicklesworthstone/destructive_command_guard/commit/e8e65d1)). ### Railway & API Pack Hardening - Expanded the Railway pack to recognize `Project-Access-Token` and `RAILWAY_TOKEN` signals, multiline API payloads, curl executable suffixes, and JSON database variable keys that can mutate production connection settings ([d6b49d5](https://github.com/Dicklesworthstone/destructive_command_guard/commit/d6b49d5), [6220da9](https://github.com/Dicklesworthstone/destructive_command_guard/commit/6220da9), [586afff](https://github.com/Dicklesworthstone/destructive_command_guard/commit/586afff), [2193c67](https://github.com/Dicklesworthstone/destructive_command_guard/commit/2193c67)). - Closed broad safe-pattern masking gaps across cloud, database, Kubernetes, package manager, backup, search, monitoring, feature flag, Kafka, and Ansible packs, including attached/equal curl methods and false dry-run text bypasses ([8e86dbc](https://github.com/Dicklesworthstone/destructive_command_guard/commit/8e86dbc), [1a1c1b0](https://github.com/Dicklesworthstone/destructive_command_guard/commit/1a1c1b0), [2690864](https://github.com/Dicklesworthstone/destructive_command_guard/commit/2690864), [c8faf44](https://github.com/Dicklesworthstone/destructive_command_guard/commit/c8faf44), [552b83d](https://github.com/Dicklesworthstone/destructive_command_guard/commit/552b83d), [7a02669](https://github.com/Dicklesworthstone/destructive_command_guard/commit/7a02669), [535b01a](https://github.com/Dicklesworthstone/destructive_command_guard/commit/535b01a)). - Kept legitimate AWS S3 `--dryrun` previews allowed while blocking deceptive dry-run-looking strings in destructive contexts ([b5bea76](https://github.com/Dicklesworthstone/destructive_command_guard/commit/b5bea76)). ### Command Parsing, Agent Detection, and Update Safety - Fixed shell redirection tokenization around attached `&>`, `&>>`, and `>&` forms so destructive append/truncate redirections are not split or hidden from filesystem rules ([87766f9](https://github.com/Dicklesworthstone/destructive_command_guard/commit/87766f9), [8aeffdc](https://github.com/Dicklesworthstone/destructive_command_guard/commit/8aeffdc), [149255c](https://github.com/Dicklesworthstone/destructive_command_guard/commit/149255c), [616cd75](https://github.com/Dicklesworthstone/destructive_command_guard/commit/616cd75)). - Reduced false positives in agent detection for domain/path substrings, wrapper-launched agents, and Windows shim-launched processes while recording the hook-protocol-detected agent type in history ([224f2f8](https://github.com/Dicklesworthstone/destructive_command_guard/commit/224f2f8), [97e91d4](https://github.com/Dicklesworthstone/destructive_command_guard/commit/97e91d4), [dba007c](https://github.com/Dicklesworthstone/destructive_command_guard/commit/dba007c), [77bfbaf](https://github.com/Dicklesworthstone/destructive_command_guard/commit/77bfbaf)). - Hardened `dcg update` so unknown latest installer tags fail closed, rollback pruning preserves the intended target, and backup artifact names are validated before use ([a4d467c](https://github.com/Dicklesworthstone/destructive_command_guard/commit/a4d467c), [5c7312b](https://github.com/Dicklesworthstone/destructive_command_guard/commit/5c7312b), [1eea079](https://github.com/Dicklesworthstone/destructive_command_guard/commit/1eea079), [ea3fcc5](https://github.com/Dicklesworthstone/destructive_command_guard/commit/ea3fcc5)). ## [v0.4.11](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.4.11) -- 2026-05-01 [Release] Clean release target for the shell tokenization regression fix from v0.4.10. This supersedes the quarantined v0.4.10 prerelease; no behavior changes were made after v0.4.10. ### Release Hygiene - Bumped the release version so official GitHub Actions can publish a clean asset set without overwriting or deleting the quarantined v0.4.10 fallback artifacts. ## [v0.4.10](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.4.10) -- 2026-05-01 [Pre-release] Patch release after v0.4.9 for a shell tokenization regression found during fresh-eyes review of nested command and process substitution handling. This release was left as a prerelease and superseded by v0.4.11 after fallback artifact publication produced an incomplete asset set. ### Shell Parsing - Preserved shell parenthesized constructs such as `$()`, `<()`, and `>()` while tokenizing commands for normalization, preventing quotes inside nested command substitutions from corrupting the normalized command stream ([41d233a](https://github.com/Dicklesworthstone/destructive_command_guard/commit/41d233a)). - Masked quoted process-substitution-looking literals before Docker pack evaluation while still blocking real input and output process substitutions that execute destructive Docker commands ([41d233a](https://github.com/Dicklesworthstone/destructive_command_guard/commit/41d233a)). ## [v0.4.9](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.4.9) -- 2026-05-01 [Release] Patch release after v0.4.8 for the remaining DCG-specific environment flag semantics and release validation fixes that need to ship in prebuilt binaries. ### CLI Reliability - Kept shell redirection ampersands such as `2>&1`, `>&2`, and `&>` inside the current command segment instead of splitting them as command separators, preserving correct downstream pack evaluation for redirected commands ([acf6803](https://github.com/Dicklesworthstone/destructive_command_guard/commit/acf6803)). - Honored documented falsey values for `DCG_NO_COLOR` and `DCG_NO_RICH` in non-clap output paths, so values such as `0`, `false`, `no`, and `off` no longer disable colors or rich output by mere presence ([14f1aac](https://github.com/Dicklesworthstone/destructive_command_guard/commit/14f1aac)). - Applied the same falsey-value semantics to `DCG_NO_UPDATE_CHECK` and `DCG_NO_SELF_HEAL`, so `0`, `false`, `no`, `n`, and `off` no longer disable update checks or self-healing by mere presence ([27ac314](https://github.com/Dicklesworthstone/destructive_command_guard/commit/27ac314)). - Kept Linux-only allowlist process inspection imports behind a Linux cfg so macOS and Windows release builds stay warning-clean ([bdcbb9b](https://github.com/Dicklesworthstone/destructive_command_guard/commit/bdcbb9b)). ### Railway Pack - Blocked Railway Public API `variableCollectionUpsert` mutations that set `replace: true`, because omitted variables are deleted and this can remove production credentials even when no database variable name appears in the payload ([fb6431e](https://github.com/Dicklesworthstone/destructive_command_guard/commit/fb6431e)). - Kept that Railway replacement mutation detector on the linear regex path for predictable hook latency ([b7aa4e2](https://github.com/Dicklesworthstone/destructive_command_guard/commit/b7aa4e2)). ### Release Validation - Isolated the Codex subprocess memory test HOME so stale pending-exception state from previous local runs cannot turn an expected Codex deny into an allow during release gates ([29d870c](https://github.com/Dicklesworthstone/destructive_command_guard/commit/29d870c)). ## [v0.4.8](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.4.8) -- 2026-05-01 [Release] Patch release after v0.4.7 for a CLI environment-variable parser fix that needs to ship in prebuilt binaries. ### CLI Reliability - Accepted documented truthy and falsey values for global boolean environment flags such as `DCG_NO_COLOR=1`, `DCG_QUIET=1`, `DCG_LEGACY_OUTPUT=1`, and `DCG_NO_SUGGESTIONS=1` instead of letting clap reject `1` as an invalid boolean ([0b350e3](https://github.com/Dicklesworthstone/destructive_command_guard/commit/0b350e3)). ## [v0.4.7](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.4.7) -- 2026-05-01 [Release] Patch release after v0.4.6 focused on Codex/Gemini installer reliability, hook protocol compatibility, and closing safe-pattern masking gaps in destructive API packs. ### Codex & Installer Reliability - Preserved invalid Codex `~/.codex/hooks.json` files instead of overwriting them during Unix installer runs, with an explicit failure reason in the install summary ([a3fc05a](https://github.com/Dicklesworthstone/destructive_command_guard/commit/a3fc05a)). - Preserved malformed Codex hook shapes on both Unix and Windows installers, including non-object `hooks` values and non-list `PreToolUse` values, instead of replacing user-edited data ([7167be6](https://github.com/Dicklesworthstone/destructive_command_guard/commit/7167be6), [f0ca794](https://github.com/Dicklesworthstone/destructive_command_guard/commit/f0ca794)). - Removed self-service bypass commands from Codex-visible denial text, so Codex sees the block reason and an explicit no-bypass instruction instead of a command it can use to allowlist and rerun the destructive operation ([a4b9a84](https://github.com/Dicklesworthstone/destructive_command_guard/commit/a4b9a84)). - Made Gemini installer reruns reset `GEMINI_BACKUP` state at the start of `configure_gemini`, preventing stale backup paths from leaking between attempts ([762f3c7](https://github.com/Dicklesworthstone/destructive_command_guard/commit/762f3c7)). - Tightened Gemini hook detection so the installer recognizes the exact dcg hook shape and reports configuration failures rather than silently treating near-matches as success ([4c9fbb2](https://github.com/Dicklesworthstone/destructive_command_guard/commit/4c9fbb2)). ### Hook & Pack Correctness - Fixed Gemini warn-severity hook output to emit `decision = "allow"` instead of `ask`, matching Gemini's accepted hook contract ([5d70198](https://github.com/Dicklesworthstone/destructive_command_guard/commit/5d70198)). - Prevented broad API safe patterns from masking destructive method-bearing requests across packs, including `curl -XDELETE`, `curl --request=DELETE`, and attached-method forms such as `-XDELETE` / `--request=DELETE` ([bdb297f](https://github.com/Dicklesworthstone/destructive_command_guard/commit/bdb297f), [08ac8a3](https://github.com/Dicklesworthstone/destructive_command_guard/commit/08ac8a3), [79915f4](https://github.com/Dicklesworthstone/destructive_command_guard/commit/79915f4)). - Blocked Redis mass key deletion pipelines and Prometheus destructive API calls that were previously hidden by overly broad safe `GET` handling ([41ec95d](https://github.com/Dicklesworthstone/destructive_command_guard/commit/41ec95d), [9f01db0](https://github.com/Dicklesworthstone/destructive_command_guard/commit/9f01db0)). - Scoped Railway original-payload rechecks to relevant compound-command segments so safe Railway API queries are not tainted by unrelated text in later shell segments, while destructive Railway mutations remain blocked ([701630f](https://github.com/Dicklesworthstone/destructive_command_guard/commit/701630f)). - Blocked Railway API mutations split across shell line continuations ([3818efc](https://github.com/Dicklesworthstone/destructive_command_guard/commit/3818efc)). ### Pack Coverage - Added Railway function deletion coverage ([f15bdf6](https://github.com/Dicklesworthstone/destructive_command_guard/commit/f15bdf6)). - Expanded the Google Cloud Storage pack to match `gcloud alpha storage` and `gcloud beta storage` release tracks ([a68ad66](https://github.com/Dicklesworthstone/destructive_command_guard/commit/a68ad66)). - Refreshed the pattern-audit document after the storage.gcs keyword widening ([dc02ff4](https://github.com/Dicklesworthstone/destructive_command_guard/commit/dc02ff4)). - Hardened the real Codex E2E harness so relative `--dcg-binary` paths are canonicalized before hook configuration, and missing option values fail with a setup error instead of shifting later arguments ([cd1b612](https://github.com/Dicklesworthstone/destructive_command_guard/commit/cd1b612), [d11de4d](https://github.com/Dicklesworthstone/destructive_command_guard/commit/d11de4d)). ## [v0.4.6](https://github.com/Dicklesworthstone/destructive_command_guard/releases/tag/v0.4.6) -- 2026-05-01 [Release] Release 0.4.6 completed the larger post-v0.4.3 hardening wave documented below. ### Security Hardening - **Railway platform protection pack** — added `platform.railway` to guard Railway CLI and Public API operations that can delete projects, environments, services, volumes, variables, and deployments. Critical rules cover project/environment/service/volume deletion and GraphQL deletion mutations (`projectDelete`, `projectScheduleDelete`, `environmentDelete`, `serviceDelete`, `volumeDelete`, `volumeInstanceDelete`). High-severity rules cover volume detach, variable deletion, database connection variable upserts (`DATABASE_URL`, `PGHOST`, `MYSQL_URL`, `REDIS_URL`, etc.), and deployment removal/stops (`railway down`, `deploymentRemove`, `deploymentStop`). Read-only commands such as `railway status`, `railway list`, `railway service list`, `railway volume list`, and safe GraphQL queries remain allowed. - **Recursive-force-delete bypass family** (`core.filesystem`): closed seven sibling-bypass families an agent could use after `rm -rf` is blocked. - `find ... -delete` on sensitive paths (Critical/High) — closes the `find -delete` path-bypass plus compound, subshell, and path-prefix variants. - `unlink ` (Critical/High) — POSIX unlink(2) primitive. - `truncate -s 0|--size=0|-s -N` on sensitive paths (Critical/High) — in-place zero/shrink. - `shred [-u|--remove|-fzu] ` (Critical/High) — DoD-style overwrite + optional unlink. - `tar --remove-files` on sensitive sources (Critical/High) — archive-then-delete masquerading as an archive operation; order-agnostic flag/source placement; `tar --remove-files -cf /dev/null /etc` (delete-only) blocked. - `dd of=` (Critical/High) — file-level overwrite (truncate-equivalent at the dd layer); operand-order agnostic; `dd of=/dev/null` (read-discard) and `dd if=/etc/passwd of=/tmp/passwd.bak` (backup) preserved; device-level dd (`of=/dev/sda`) is `system.disk`'s scope. - `mv ` (Critical) — closes the canonical cross-segment bypass `mv /etc /tmp/x && rm -rf /tmp/x` where each segment is allowed individually but together destroys `/etc`. Blocks any mv that mentions a sensitive path (source OR destination) including in-place renames within /etc; tmp-family moves remain allowed. - Sensitive-source propagation chains (Critical) — blocks phase-1 data-flow bypasses for `cp -a/-al && rm -rf `, `ln -s && rm -rf /.`, and `rsync -a && rm -rf `. The filesystem rm fast-path now parses compound segments so ordinary temp cleanup stays allowed while propagation chains are classified before the rm fallback rules. - `> ` (Critical) — Bash output redirects (`>`, `>|`, `&>`, `1>`, `2>` with optional `|` force-overwrite) truncate the target file to zero bytes; bare `> /etc/passwd`, `: > /etc/passwd`, `echo > /etc/passwd`, and numbered-FD variants all destroy file content via shell syntax alone (no destructive binary involved). Append (`>>`) is correctly preserved via negative lookbehind. Per scope decision: only the Critical root-home tier ships — a `-general` rule would block legitimate `make > build.log` workflows. Two supporting changes: (a) the `should_fallback_to_full_normalized_keyword_scan` quick-reject helper now fires whenever a redirect operator is present (previously gated on path-prefix normalization), so redirect keywords match outside the executable span; (b) `sanitize_for_pattern_matching` now exits all-args-data masking on redirect operators so `echo > /etc/passwd` no longer hides the destructive target. - **mkswap rule added to `system.disk`** (`git_safety_guard-8kh4`) — `mkswap /dev/sdb` formats a partition as a swap area with the same blast radius as `mkfs`. Previously slipped through because mkswap is a separate binary and the existing `mkfs(?:\.[a-z0-9]+)?` regex only matched `mkfs.*` variants. Ships with the `mkswap` keyword in PACK_ENTRIES, a destructive `mkswap` rule (High), and a safe `mkswap-check` carve-out for read-only `mkswap --check` inspection. - **`dcg update` verifies install.sh / install.ps1 before exec** (`git_safety_guard-ythp`) — `self_update_unix` previously did `curl -fsSL