From 9e38fd7eeb7cd3a7b8d6ea8aa99d631ed40623c5 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Tue, 14 Jul 2026 00:28:59 -0400 Subject: [PATCH 1/8] feat(claude-config-audit): add permission-hygiene grant audit + convention Add a durable guardrail against fragile Claude Code permission grants. Enforceable check: a new `permission-hygiene` skill whose deterministic `permission-rule-check.sh` detector scans skill/command/agent frontmatter `allowed-tools` and settings.json/settings.local.json `permissions.allow`, flagging three anti-patterns and recommending the bare-command-on-PATH pattern: - P1 interpreter-wildcard / blanket allow rules that Claude Code drops on entering auto mode (Bash(*), Bash(python*), Bash(bash *), package-manager runners, Bash(*.py:*)); narrow rules like Bash(npm test) carry over and are not flagged. - P2 hardcoded absolute machine/user paths (Bash rules match literally with no ~/$HOME/env expansion). - P3 a plugin settings.json that declares an inert `permissions` block (only agent/subagentStatusLine are supported), so the operative rule must be added by the operator to user-global ~/.claude/settings.json. Ships with a 27-check contract test (positive + negative fixtures, including the narrow-rule-not-flagged case), reference/criteria.md, and evals/evals.json. settings.local.json is parsed for permissions.allow only, never echoed. Scope vs settings-audit (file correctness) is explicit and routes out. Convention: docs/conventions/permission-rule-hygiene (README + CHANGELOG) states the principle, the three anti-patterns, the correct bare-name+PATH / plugin-bin pattern, and the operator-setup boundary, each with official-doc citations; the skill's criteria link to it rather than restating. Detector and fixtures assemble machine-path strings from fragments and the docs use placeholders so no contiguous machine-path literal sits in a committed file, keeping the repo's own machine-specific-path lane clean. Co-authored-by: Claude Opus 4.8 (1M context) --- README.md | 2 +- .../permission-rule-hygiene/CHANGELOG.md | 17 ++ .../permission-rule-hygiene/README.md | 119 +++++++++++ .../.claude-plugin/plugin.json | 6 +- plugins/claude-config-audit/README.md | 25 ++- .../skills/permission-hygiene/SKILL.md | 80 +++++++ .../permission-hygiene/evals/evals.json | 65 ++++++ .../permission-hygiene/reference/criteria.md | 96 +++++++++ .../scripts/permission-rule-check.sh | 202 ++++++++++++++++++ .../scripts/permission-rule-check.test.sh | 179 ++++++++++++++++ 10 files changed, 784 insertions(+), 7 deletions(-) create mode 100644 docs/conventions/permission-rule-hygiene/CHANGELOG.md create mode 100644 docs/conventions/permission-rule-hygiene/README.md create mode 100644 plugins/claude-config-audit/skills/permission-hygiene/SKILL.md create mode 100644 plugins/claude-config-audit/skills/permission-hygiene/evals/evals.json create mode 100644 plugins/claude-config-audit/skills/permission-hygiene/reference/criteria.md create mode 100755 plugins/claude-config-audit/skills/permission-hygiene/scripts/permission-rule-check.sh create mode 100755 plugins/claude-config-audit/skills/permission-hygiene/scripts/permission-rule-check.test.sh diff --git a/README.md b/README.md index 0ebaaa98d..c58bda63d 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Browse and manage with `/plugin`. To refresh after updates: `/plugin marketplace | [`docs-hygiene`](plugins/docs-hygiene) | Skills | Documentation-hygiene toolkit of five skills: `/docs-hygiene:compress` (flavor-trim markdown behind a semantic-diff safety net), `/docs-hygiene:declutter` (classify markdown noise, read-only), `/docs-hygiene:extract-ssot` (deduplicate repeated content into a single source of truth), `/docs-hygiene:encapsulation-audit` (detect citations into skill-private surfaces), and `/docs-hygiene:rename-references` (sweep stale references after renames). | | [`fable-5-playbook`](plugins/fable-5-playbook) | Skill | Ships Claude Fable 5's operating doctrine as an on-demand knowledge skill — core standing instructions plus twelve trigger-routed chapters (calibration, reasoning moves, planning, debugging, orchestration, verification, recovery, trust boundaries, and more) and an Opus-adaptation chapter for non-Fable models. | | [`firecrawl`](plugins/firecrawl) | Skill | Web scraping, search, crawling, URL discovery, browser interaction, and local file parsing through the `firecrawl-cli` binary — results written to disk and read back selectively to keep large pages out of context, plus a gated maintainer update flow tracking the upstream CLI and skill source. | -| [`claude-config-audit`](plugins/claude-config-audit) | Skills | Keeps a repo's Claude Code configuration healthy via three report-first audit skills: `settings-audit` (config files vs upstream truth, with live plugin-drift detection), `memory-health` (CLAUDE.md / rules / auto-memory against official-doc criteria), and `automation-deep-dive` (evidence-gated verdicts on automation gaps). | +| [`claude-config-audit`](plugins/claude-config-audit) | Skills | Keeps a repo's Claude Code configuration healthy via four report-first audit skills: `settings-audit` (config files vs upstream truth, with live plugin-drift detection), `memory-health` (CLAUDE.md / rules / auto-memory against official-doc criteria), `automation-deep-dive` (evidence-gated verdicts on automation gaps), and `permission-hygiene` (allow-rule / allowed-tools grants for auto-mode durability and machine portability). | | [`work-items`](plugins/work-items) | Skill | Manages development work items through a provider-neutral tracker seam (GitHub the bound adapter today): dashboard, taxonomy-labeled creation, a race-safe assignee-plus-lease claim protocol for multi-agent pickup, recurring-schedule checks, TODO scanning, stale-lease auditing, plan decomposition into vertical slices, and structured triage. | | [`discovery`](plugins/discovery) | Skills | Structured discovery before changes. Ships four skills: `/discovery:explore` and `/discovery:explore-deep` (six-dimension codebase exploration, inline or in a forked subagent) plus `/discovery:research` and `/discovery:research-deep` (three-phase multi-source external research with source tiers, falsification, and recency gates). | | [`playwright`](plugins/playwright) | Skill | Live E2E browser automation through Microsoft's `@playwright/cli` — named sessions, accessibility-ref snapshots (click/fill by ref), screenshots, console/network capture, mocking, tracing, video, and auth state, with artifacts written to disk so only paths enter context, plus Windows/orchestrator overlays and a gated maintainer update flow tracking the upstream npm skill. | diff --git a/docs/conventions/permission-rule-hygiene/CHANGELOG.md b/docs/conventions/permission-rule-hygiene/CHANGELOG.md new file mode 100644 index 000000000..9fa156e65 --- /dev/null +++ b/docs/conventions/permission-rule-hygiene/CHANGELOG.md @@ -0,0 +1,17 @@ +# Permission Rule Hygiene Convention — Changelog + +Notable changes to the permission-rule-hygiene convention. The convention states a principle and three +anti-patterns; it is enforced by the `claude-config-audit` plugin's `permission-hygiene` skill (checks +P1/P2/P3), whose detector and criteria version independently of this document. + +## 1.0 — 2026-07-14 + +Initial published convention. + +- Principle: the operative allow-rule for a guarded code-execution helper must be a narrow, + machine-independent, bare-command rule the operator adds to user-global settings. +- Anti-pattern 1 — interpreter-wildcard / blanket allow rules dropped in auto mode. +- Anti-pattern 2 — hardcoded absolute machine/user paths (Bash rules match literally, no expansion). +- Anti-pattern 3 — assuming a skill or plugin can self-grant an auto-mode-gated action class. +- Correct pattern: bare command on the Bash tool PATH (pre-plugin PATH shim, post-migration plugin + `bin/`) allowed narrowly by bare name, with an operator-setup boundary note. diff --git a/docs/conventions/permission-rule-hygiene/README.md b/docs/conventions/permission-rule-hygiene/README.md new file mode 100644 index 000000000..ec36ebdcd --- /dev/null +++ b/docs/conventions/permission-rule-hygiene/README.md @@ -0,0 +1,119 @@ +# Permission Rule Hygiene Convention + +A marketplace-wide convention for writing Claude Code permission grants that actually take effect — +specifically, grants for the auto-mode-gated action classes (arbitrary code execution) that a skill, +command, or plugin wants to run without a prompt. + +The principle: **the operative allow-rule for a guarded code-execution helper must be a narrow, +machine-independent, bare-command rule that the operator adds to user-global settings — never an +interpreter-wildcard grant, never a hardcoded machine path, and never a self-granted rule a skill or +plugin ships expecting it to work.** The three anti-patterns below each break that in a different way; +the [correct pattern](#the-correct-pattern) fixes all three at once. + +Enforced by the [`permission-hygiene`](../../../plugins/claude-config-audit/skills/permission-hygiene) +skill in the `claude-config-audit` plugin, which scans skill/command/agent frontmatter `allowed-tools` +and `settings.json` / `settings.local.json` `permissions.allow` and flags each anti-pattern (checks +P1/P2/P3). + +## Why this convention exists + +Running this convention's own detector against this marketplace surfaced six pre-existing +interpreter/runner-led frontmatter grants (shapes like `Bash(bash