diff --git a/plugins/guardrails/.claude-plugin/plugin.json b/plugins/guardrails/.claude-plugin/plugin.json index f658731cf4..deb0c8763f 100644 --- a/plugins/guardrails/.claude-plugin/plugin.json +++ b/plugins/guardrails/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "guardrails", - "version": "0.15.0", + "version": "0.15.1", "description": "Eleven safety guards that block secret/credential writes, hardcoded machine-specific paths, git hook-bypass attempts, irreversible git operations (force-push, reset --hard, worktree-wide checkout/restore discards), Bash file-write workarounds that circumvent Write/Edit hooks, commit subjects and gh pr create titles that violate the repo's tracked team convention (when one is declared in .claude/source-control.md), (advisory) hallucinated CLI flags, (advisory) /plugin:skill references that do not resolve, (advisory) un-throttled Workflow fan-out that risks burst 529s, and (advisory) direct git commit/gh pr create calls bypassing this marketplace's own commit/pull-request skills — each independently toggleable.", "author": { "name": "Melodic Software", diff --git a/plugins/guardrails/CHANGELOG.md b/plugins/guardrails/CHANGELOG.md index 86cc5fbfc1..9b45536bf1 100644 --- a/plugins/guardrails/CHANGELOG.md +++ b/plugins/guardrails/CHANGELOG.md @@ -3,6 +3,37 @@ All notable changes to the `guardrails` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.15.1] + +### Fixed + +- **PreToolUse blocking guards were declared with `timeout: 10`/`15` — 40-60x below the platform's + own documented `command`-hook default of 600s for `PreToolUse` (only `UserPromptSubmit` (30) and + `MessageDisplay` (10) lower it; `PreToolUse` does not — , + fetched 2026-07-25) — causing the harness to kill them before completion under real machine load + and let the guarded tool call proceed with no `permissionDecision` from that guard.** Measured at + 86.1% of PreToolUse runs killed at the declared timeout across 3,923 runs on one machine + (melodic-software/claude-code-plugins#1345). Confirmed against this session's own local + `~/.claude/projects/*/*.jsonl` transcript: a `hook_cancelled` attachment for + `block-convention-violation.sh` (`timedOut: true`, `durationMs: 10184` against `timeoutMs: 10000`) + was immediately followed by the guarded Bash tool call executing and returning a real result — the + guard's verdict was silently lost, not merely slow. Standalone timing of all seven affected guards + in this repo (no concurrent hook load) completed in well under 1.5s each, and the source contains no + network calls or unbounded loops — confirming the guards are not inherently slow; the declared + timeout was simply provisioned far below what the platform allows and below what real (contended) + runs need. `timeout` raised from 10/15 to **60** (10-40x more headroom over the every real duration + sample this investigation captured, while staying well short of the 600s platform default so a + genuinely hung process is still bounded) for the seven **blocking** PreToolUse guards: + `secret-pattern-detection`, `hardcoded-path-check`, `block-no-verify`, `block-dangerous-git`, + `block-hook-bypass`, `block-noncanonical-commit`, `block-convention-violation`. The two **advisory** + PreToolUse hooks (`flag-commit-pr-skill-bypass`, `workflow-resilience-check`, which never block + regardless of outcome) and the PostToolUse hooks are unchanged — a missed advisory notice is not the + fail-open security defect this fix addresses. This mitigation narrows the timeout-driven fail-open + window; it does not remove it — a harness-killed hook process cannot itself report a decision, and + what should happen to the guarded tool call when a *blocking* guard is killed (deny by default vs. + today's silent fallback) is a harness-level policy question outside a plugin's control, tracked + separately. + ## [0.15.0] ### Added diff --git a/plugins/guardrails/hooks/hooks.json b/plugins/guardrails/hooks/hooks.json index 7a15235d0d..b12e8e3e02 100644 --- a/plugins/guardrails/hooks/hooks.json +++ b/plugins/guardrails/hooks/hooks.json @@ -7,13 +7,13 @@ { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/secret-pattern-detection.sh", - "timeout": 15, + "timeout": 60, "statusMessage": "Checking for secrets..." }, { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/hardcoded-path-check.sh", - "timeout": 15, + "timeout": 60, "statusMessage": "Checking for hardcoded paths..." } ] @@ -24,19 +24,19 @@ { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/block-no-verify.sh", - "timeout": 10, + "timeout": 60, "statusMessage": "Checking for --no-verify bypass..." }, { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/block-dangerous-git.sh", - "timeout": 10, + "timeout": 60, "statusMessage": "Checking for dangerous git commands..." }, { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/block-hook-bypass.sh", - "timeout": 10, + "timeout": 60, "statusMessage": "Checking for hook-bypass attempts..." }, { @@ -53,13 +53,13 @@ { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/block-noncanonical-commit.sh", - "timeout": 10, + "timeout": 60, "statusMessage": "Checking commit-message convention..." }, { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/block-convention-violation.sh", - "timeout": 10, + "timeout": 60, "statusMessage": "Checking commit subject / PR title against the team convention..." } ]