Skip to content
Merged
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ user opts in with `/plugin enable`; an existing install is never flipped by cata

### Security

- [`guardrails`](plugins/guardrails) — Nine 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) 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.
- [`guardrails`](plugins/guardrails) — 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.

### Workflow

Expand Down
10 changes: 8 additions & 2 deletions plugins/guardrails/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "guardrails",
"version": "0.14.3",
"description": "Nine 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) 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.",
"version": "0.15.0",
"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",
"email": "info@melodicsoftware.com"
Expand Down Expand Up @@ -68,6 +68,12 @@
"description": "Advise on hallucinated CLI flags written to files (never blocks)",
"default": true
},
"skill_reference_verify_enabled": {
"type": "boolean",
"title": "skill-reference-verify guard",
"description": "Advise when markdown cites a /plugin:skill reference this repo owns but cannot resolve (never blocks)",
"default": true
},
"workflow_resilience_check_enabled": {
"type": "boolean",
"title": "workflow-resilience-check guard",
Expand Down
41 changes: 41 additions & 0 deletions plugins/guardrails/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,47 @@
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.0]

### Added

- `skill-reference-verify` (advisory, PostToolUse Write|Edit): flags a
`/plugin:skill` reference in markdown that does not resolve. Gated twice — it
does nothing outside a marketplace repo, and within one it only adjudicates a
plugin that repo's own manifests own. Resolution goes through manifest `name`
and skill frontmatter `name`; a renamed skill's DIRECTORY name is deliberately
not an alias, since treating it as one would suppress exactly the stale
pre-rename references this guard exists to catch. The reference is the leading
command token of a code span, so argument-bearing invocations
(`/plugin:skill --apply`) are scanned. `CHANGELOG.md` is excluded as an
append-only historical record: a rename entry must keep naming the old command.
Declared **detect-then-judge**, not deterministic — globbing a plugins tree is
exact only where the reference is locally owned, so the finding is a prompt for
a human verdict and never an auto-fix.
- A README enforceability-tier section stating each guard's oracle class, so the
detect-then-judge guard cannot be read as deterministic.

### Fixed

- README guard counts were stale before this change: the prose said "nine safety
guards" and the table omitted `block-convention-violation` while ten were
wired. Counts are now measured against the manifest's toggle set, and the
missing row is present.

### Not shipped

- An `asserted-path-verify` guard was built alongside this one and withdrawn on
measurement. Swept across all 975 tracked markdown files it fired on 23.7% of
them — roughly one in four writes — producing 389 findings with **zero** true
positives. 72% were consumer-project config paths (`.claude/**` and similar)
that a doc describes for a CONSUMING repo and that correctly do not exist in a
marketplace; its first-segment gate passed only because this repo happens to
carry same-named top-level directories. Fixing the three dominant causes still
left ~4% firing at zero true positives, so a repo-root filesystem test is the
wrong oracle for a repo whose docs are largely about other repos' trees. The
measurement is attached to its follow-up issue for rescoping rather than
discarded.

## [0.14.3]

### Documentation
Expand Down
17 changes: 14 additions & 3 deletions plugins/guardrails/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# guardrails

A Claude Code plugin bundling nine **safety guards** that catch risky agent
A Claude Code plugin bundling eleven **safety guards** that catch risky agent
actions the moment they happen — before a write lands or a bash command runs.
Each guard is independently toggleable, so you run exactly the subset you want.

Expand All @@ -16,12 +16,23 @@ Each guard is independently toggleable, so you run exactly the subset you want.
| **cli-flag-verify** | PostToolUse · Write \| Edit | **Advisory** (exit 0) | Hallucinated CLI flags — a `--flag` written as a command that does not exist in the binary's actual `--help` output. Surfaces via `additionalContext`, never blocks. |
| **workflow-resilience-check** | PreToolUse · Workflow | **Advisory** (exit 0) | Un-throttled Workflow fan-out — a script calling `parallel()` / `pipeline()` with no wave-cap throttle (`inWaves` / `inWavesPipeline`) and no retry wrapper (`agentRetry`), which risks a burst 529 under wide Opus fan-out. Surfaces a resilience checklist via `additionalContext`, never blocks. |
| **block-noncanonical-commit** | PreToolUse · Bash | **Blocks** (exit 2) | `git commit` that does not pipe its message via `-F -` / `--file -` — `-m` flattens newlines unpredictably across shells. Exempt: `--amend`, `-C`/`-c`/`--reuse-message`/`--reedit-message`, `--fixup`/`--squash`, `-F <path>`, and any commit taken while a merge/rebase/cherry-pick/revert is in progress. Resolves `bash -lc` wrappers and git aliases (inline `-c` and persisted config alike). |
| **block-convention-violation** | PreToolUse · Bash | **Blocks** (exit 2) | A commit subject or `gh pr create --title` that violates the team-tracked convention pattern declared in `.claude/source-control.md`. No tracked pattern means no enforcement. Same exemptions as `block-noncanonical-commit`. |
| **flag-commit-pr-skill-bypass** | PreToolUse · Bash | **Advisory** (exit 0) | Any `gh pr create`, bypassing this marketplace's own `/pull-request create` skill. Only fires when the consuming project's own `.claude/settings.json` enables the `source-control` plugin — silent otherwise. Surfaces via `additionalContext`, never blocks. |
| **skill-reference-verify** | PostToolUse · Write \| Edit | **Advisory** (exit 0) | A `` `/plugin:skill` `` reference in markdown that does not resolve. Only fires inside a marketplace repo, and only for a plugin that repo's own manifests own — a reference to another marketplace is left alone. Resolves through manifest and frontmatter `name`, so a renamed directory still matches. Surfaces via `additionalContext`, never blocks. |

The six blocking guards feed their stderr message back to Claude as
actionable fix guidance. The three advisory guards surface their findings the same
The seven blocking guards feed their stderr message back to Claude as
actionable fix guidance. The four advisory guards surface their findings the same
way but always allow the operation.

### Enforceability tiers

Ten guards are **deterministic** — their oracle is a mechanical test with no
judgment step. `skill-reference-verify` is **detect-then-judge**: globbing a
plugins tree is exact only inside a marketplace repo that owns the referenced
plugin, so its finding is a prompt for a human verdict, never a determination and
never an auto-fix. `cli-flag-verify` is deterministic in its oracle but advisory in
its action, because a written claim can be deliberately forward-looking.

### Scope notes

- **Hook-manager coverage.** `block-no-verify` recognizes the disable env-var
Expand Down
6 changes: 6 additions & 0 deletions plugins/guardrails/hooks/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@
"command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/cli-flag-verify.sh",
"timeout": 30,
"statusMessage": "Verifying CLI flags..."
},
{
"type": "command",
"command": "\"${CLAUDE_PLUGIN_ROOT}\"/hooks/skill-reference-verify.sh",
"timeout": 30,
"statusMessage": "Verifying skill references..."
}
]
}
Expand Down
Loading