Back to skills
extension
Category: Development & EngineeringNo API key required

audit-permissions

-

personAuthor: jakexiaohubgithub

Audit Claude Permissions

Scan project-local Claude Code settings files, aggregate permission patterns, and recommend promotions to global configuration.

Workflow Overview

This audit runs in three phases, each as a separate task. Use TaskCreate at the start to create all three tasks, then work through them sequentially with user input via AskUserQuestion.

Phase 1: Promote to Global - Review candidates and add selected permissions to global config Phase 2: Clean Up Redundant - Remove local permissions now covered by global Phase 3: Security Hygiene - Review and remove risky or stale permissions

Pre-flight Check

To avoid permission prompts during the audit, consider adding these to global settings:

  • Read(~/.claude/settings.json) - read global settings
  • Read(**/.claude/settings.local.json) - read all local settings files

Initial Setup

  1. Run the discovery and extraction pipeline:
${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/discover-settings.sh | xargs ${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/extract-permissions.py
  1. Read global settings from ~/.claude/settings.json

  2. Create tasks for the three phases:

TaskCreate: "Review and promote permissions to global config"
TaskCreate: "Clean up redundant local permissions"
TaskCreate: "Review security hygiene issues"
  1. Analyze the data and categorize permissions (see Categorization Rules below)

Phase 1: Promote to Global

Goal: Identify permissions worth adding to global config and get user approval.

Present Findings

Show a summary table of promotion candidates:

## Promotion Candidates

### Strong Recommendations (safe patterns, multiple projects)

| Permission | Projects | Suggested Global Pattern |
| ---------- | -------- | ------------------------ |
| ...        | ...      | ...                      |

### Moderate Recommendations (review carefully)

| Permission | Projects | Notes |
| ---------- | -------- | ----- |
| ...        | ...      | ...   |

### Cross-Project File Patterns

[If any Read/Write/Edit permissions reference paths outside their project directory
and appear in multiple projects, flag them here. Example: multiple projects have
`Write(~/.config/some-tool/config.json)` - might indicate a shared config worth
adding globally.]

Get User Decision

Use AskUserQuestion to let the user decide:

Question: "Which permissions should I add to global settings?"
Options:
- "Add all strong recommendations"
- "Add strong + moderate recommendations"
- "Let me pick specific ones" (then list individually)
- "Skip - don't add any"

Apply Changes

If user approves additions:

  1. Add selected permissions to ~/.claude/settings.json
  2. Respect existing logical groupings (git, nix, gh, etc.)
  3. Sort alphabetically within groups
  4. Mark Phase 1 task as completed

Phase 2: Clean Up Redundant

Goal: Remove local permissions that are now covered by global config.

Preview Cleanup

Run the cleanup script in dry-run mode:

${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/discover-settings.sh | ${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/cleanup-redundant.py

Present Findings

Show what would be removed:

## Redundant Permissions

| File      | Permissions to Remove | Remaining |
| --------- | --------------------- | --------- |
| project-a | 5 (ls:_, grep:_, ...) | 12        |
| project-b | 3 (gh api:\*, ...)    | 8         |
| ...       | ...                   | ...       |

**Total:** X permissions across Y files

Get User Decision

Use AskUserQuestion:

Question: "Should I remove these redundant permissions from local files?"
Options:
- "Yes, clean them up"
- "Show me the full list first"
- "Skip cleanup"

Apply Changes

If user approves:

${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/discover-settings.sh | ${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/cleanup-redundant.py --apply

Mark Phase 2 task as completed.


Phase 3: Security Hygiene

Goal: Identify and remove risky, stale, or overly broad permissions.

Identify Issues

Flag permissions that match these patterns:

High Risk (recommend removal):

  • Bash(curl:*), Bash(wget:*) - network exfiltration risk
  • Bash(rm:*) - can delete any file
  • Bash(source:*) - executes arbitrary scripts
  • Bash(eval:*) - arbitrary code execution

Moderate Risk (review):

  • Bash(git reset:*), Bash(git checkout:*) - can discard work
  • Bash(pkill:*), Bash(kill:*) - process termination
  • Bash(python:*), Bash(python3:*), Bash(node:*) - arbitrary code (flag if user hasn't consciously chosen this)

One-Off Cruft (safe to remove):

  • Hardcoded file paths (e.g., Bash(, prettier --write /full/path/to/file.md))
  • Incomplete shell constructs (Bash(done), Bash(for file in *.rs))
  • Very specific commands with no wildcards that look like debugging artifacts
  • Duplicate entries

Cross-Project File Access:

  • Read, Write, or Edit permissions for paths outside the project
  • Flag if the same external path appears in multiple projects (potential global candidate)
  • Flag broad patterns like Write(~/.config/*) as security concerns

Present Findings

## Security Hygiene Review

### High Risk - Recommend Removal

| Permission     | Project   | Risk              |
| -------------- | --------- | ----------------- |
| `Bash(curl:*)` | project-x | Data exfiltration |
| ...            | ...       | ...               |

### Moderate Risk - Review

| Permission | Project | Risk |
| ---------- | ------- | ---- |
| ...        | ...     | ...  |

### One-Off Cruft

| Permission                                           | Project   |
| ---------------------------------------------------- | --------- |
| `Bash(, prettier --write /path/to/specific/file.md)` | project-y |
| ...                                                  | ...       |

### External File Access

| Permission                     | Projects   | Path                            |
| ------------------------------ | ---------- | ------------------------------- |
| `Write(~/.config/tool/config)` | 3 projects | Shared config - consider global |
| `Edit(/etc/hosts)`             | 1 project  | System file - review necessity  |

Get User Decision

Use AskUserQuestion:

Question: "How should I handle the security hygiene items?"
Options:
- "Remove all flagged items"
- "Remove high risk + cruft only"
- "Let me review each category"
- "Skip - keep everything"

If user wants to review categories, ask about each:

  • High risk items
  • Moderate risk items
  • One-off cruft
  • External file access

Apply Changes

Edit each affected settings.local.json to remove approved items.

Mark Phase 3 task as completed.


Scripts

All scripts are in ${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/.

  • scripts/discover-settings.sh - Finds all .claude/settings.local.json files across ~ using fd with sensible exclusions (Library, node_modules, .git, etc.). Max depth of 5 for performance.
  • scripts/extract-permissions.py - Aggregates permissions from multiple settings files. Outputs JSON with each permission, occurrence count, and list of projects using it. Sorted by count descending.
  • scripts/cleanup-redundant.py - Removes permissions from local files that are covered by global config. Dry-run by default; use --apply to modify files.

Usage examples:

# Extract and aggregate all permissions
${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/discover-settings.sh | xargs ${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/extract-permissions.py

# Preview redundant permission cleanup (dry-run, default)
${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/discover-settings.sh | ${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/cleanup-redundant.py

# Actually remove redundant permissions
${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/discover-settings.sh | ${CLAUDE_PLUGIN_ROOT}/skills/audit-permissions/scripts/cleanup-redundant.py --apply

Categorization Rules

Reasonable Global Candidates

Patterns worth promoting. These operate on local project code or perform read-only operations.

Git Commands (read-only): git branch:*, git diff:*, git log:*, git show:*, git status:*

File Inspection (read-only): cat:*, head:*, tail:*, ls:*, find:*, grep:*, du:*

Build and Check Commands: cargo build:*, cargo test:*, cargo check:*, go build:*, go test:*, npm run build:*, npm run test:*, deno check:*, deno lint:*, xcodebuild:*

System Utilities: open:*, pbcopy, pbpaste, lsof:*, ps:*

Nix Commands: nix build:*, nix-build:*, nix develop:*, nix eval:*, nix flake:*, nix path-info:*, nix-prefetch-url:*, nh darwin build:*

Homebrew (read-only): brew info:*, brew search:*

GitHub CLI: gh api:*, gh issue list:*, gh issue view:*, gh pr list:*, gh pr view:*, gh pr diff:*, gh pr checks:*, gh search:*, gh run list:*, gh run view:*

Wildcards: * --help *, * --version

Pattern Generalization

When promoting, generalize cautiously - only for safe patterns:

| Local Pattern | Global Pattern | Notes | | ----------------------------- | ----------------------- | ---------------------------- | | Bash(npm run build) | Bash(npm run build:*) | Safe - runs project scripts | | Bash(cargo test --release) | Bash(cargo test:*) | Safe - tests local code | | Bash(nix build .#package) | Bash(nix build:*) | Safe - sandboxed builds | | Bash(python3 script.py) | Keep specific or skip | Risky - arbitrary code | | WebFetch(domain:github.com) | Keep as-is | Domain patterns don't change |

Formatting Rules for Global Settings

When adding to ~/.claude/settings.json:

  • Respect existing logical groupings (git, file inspection, nix, brew, gh, system utilities, build tools, wildcards, Skills, MCP tools)
  • Within each group, sort alphabetically
  • Place new permissions in the appropriate group based on command prefix