security-permissions · git:20260708.e42b71f · 2026-07-08 · sha256 ca009774bb8bb9a9

security-permissions git:20260708.e42b71fA

Immutable. This exact content is served forever at /api/v1/blob/ca009774bb8bb9a9.

---
name: "security-permissions"
description: "Risk-graded permission audit - wraps native /fewer-permission-prompts with allow/ask/deny tiers"
---
<!-- GENERATED by claude-power-pack - scripts/codex-skill-sync.py; edit .claude/commands/security/permissions.md instead -->

## Codex harness adaptations

Generated from a Claude Code command. Where the procedure references these Claude-only surfaces, adapt as follows:

- MCP tools: use the MCP servers configured in `~/.codex/config.toml`, or fall back to the referenced repo scripts and CLI entry points.
- Helper scripts referenced as `scripts/<name>` are bundled under `scripts/` in this skill directory (byte-identical copies from the claude-power-pack checkout); some expect sibling repo resources, so prefer a full checkout when one is available.

# Security: Permissions Audit

A risk-graded wrapper around Claude Code's native **`/fewer-permission-prompts`**.
The native skill does a binary read-only / skip split and emits an allowlist only.
This command adds `scripts/classify-tool-risk.py` to sort every observed tool call
into risk tiers, then proposes a full **allow / ask / deny** policy.

> Use the native `/fewer-permission-prompts` for the quick read-only allowlist.
> Use this when you also want the mutation and danger tiers surfaced and guarded
> (it never edits `permissions.ask` / `permissions.deny` unless you asked for the
> graded policy, which this command does by design).

## What it produces

- **allow** - read-only commands not already auto-allowed (e.g. `git fetch`) +
  the *safe, reversible* subset of local writes (`git add`, `git commit`,
  `mkdir`, `git worktree add`) + read-only MCP tools seen >= 3 times.
- **ask** - the recoverable-but-dangerous tier, gated *even under auto-accept*:
  `git push --force`, `git reset --hard`, `rm -rf`.
- **deny** - secrets that must never be auto-edited: `.env`, `*.pem`, `*.key`,
  `id_rsa*`.

## Steps

1. **Run the graded classifier** over recent transcripts:
   ```bash
   python3 scripts/classify-tool-risk.py --limit 50
   ```
   (Run from the CPP checkout. It scans `~/.claude/projects/**/*.jsonl` across all
   projects, not just the current one.)

2. **Present the tiers** as a table (tier, count, examples, verdict). Note that
   the READONLY-AUTO tier is already covered by Claude Code and needs no rule -
   do not propose those (see the native skill's auto-allow list).

3. **Propose the policy from the tiers:**
   - `allow`: READONLY-ADDABLE + the SAFE subset of WRITE-LOCAL. Exclude anything
     with a data-loss mode - `git checkout`, `git rm`, `git branch -D`,
     `git worktree remove`, `git reset` classify as DESTRUCTIVE, not allow.
     CODE-EXEC / DUAL-USE-NET / SCRIPT-EXEC are **never** allowlisted (arbitrary
     execution or ambiguous network I/O).
   - `ask`: the DESTRUCTIVE tier (force push, `reset --hard`, `rm -rf`) so it
     prompts even under auto-accept.
   - `deny`: secret files (`.env`, `**/.env`, `*.pem`, `*.key`, `id_rsa*`).

4. **Merge into the project `.claude/settings.json`** (NOT `settings.local.json`,
   NOT `~/.claude/settings.json`): preserve existing keys and entries,
   de-duplicate, never remove or reorder. Precedence is **deny > ask > allow**, so
   a secret `deny` overrides a broad `Edit(**)` allow.

5. **Report**: what was added to each tier, what was already covered by Claude
   Code's auto-allow (so no rule was needed), and what was excluded and why
   (e.g. dropped `python3`/`uv`/`make` - arbitrary code execution; dropped
   `curl`/`gh api` - dual-use network).

## File-edit scope (the git-tracked nuance)

To auto-allow file edits "only within the git commit list": Claude Code
permissions are path-glob based, not git-aware, so this cannot be expressed
directly. Two implementations:

- **Approximation (default):** `Edit(**)` / `Write(**)` for the repo tree plus a
  `deny` list for sensitive gitignored files (`.env`, keys).
- **Exact (offer):** a `PreToolUse` hook that runs `git check-ignore` on the edit
  target and blocks ignored paths. This literally scopes edits to tracked files.
  Offered, not applied by default.

## Notes

- Wraps, does not replace, the native `/fewer-permission-prompts` (a built-in
  Claude Code skill, not a CPP skill - which is why its graded extension lives
  in CPP).
- Classifier: `scripts/classify-tool-risk.py` (the **canonical** risk taxonomy).
  Re-run anytime for a fresh view.
- Complements the **real-time** side: the `#482` permission-census hook
  (`scripts/hook-permission-census.sh`) captures prompts as they happen and
  vendors the same taxonomy inline. This command is the **retroactive** side
  (mine all transcripts, propose a policy in one pass). `scripts/tool-risk-drift.py`
  guards the two taxonomies' safety-critical sets in sync.
- The destructive `ask`/`deny` guards are more protective in
  `~/.claude/settings.json` (global, every project); the allowlist is
  project-scoped by design. Offer to promote the guards to global.