audit-permissions — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited audit-permissions (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Scan project-local Claude Code settings files, aggregate permission patterns, and recommend promotions to global configuration.
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.
readlink -f ~/.claude/settings.jsonIf the global settings file is a symlink, note the real path. All writes to ~/.claude/settings.json must edit the symlink target, not create a new file that replaces the symlink.
~/.claude/cc-maintenance.local.md (if it exists). See User Preferences section below. Apply any configured defaults (risk tolerance, auto-cleanup preference).~/.claude/CLAUDE.md to identify tool preference policies for Phase 3 policy conflict detection.scripts/discover-settings.sh | xargs scripts/extract-permissions.py~/.claude/settings.json — compare against the real allow list, not just the static examples in this skill.TaskCreate: "Review and promote permissions to global config"
TaskCreate: "Automated redundancy cleanup"
TaskCreate: "Judgment calls: security, policy, and cruft"Goal: Identify permissions worth adding to global config and get user approval.
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.]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"If user approves additions:
~/.claude/settings.json (or symlink target)Bash(cmd *) not Bash(cmd:*)Goal: Remove local permissions now covered by global config. This is mechanical — the script identifies exact matches; user just sanity-checks the list.
Run the cleanup script in dry-run mode:
scripts/discover-settings.sh | scripts/cleanup-redundant.pyShow 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 filesThe script also normalizes any remaining colon-syntax (Bash(cmd:*)) to space-syntax (Bash(cmd *)) when applying.
If auto_cleanup_redundant: true in user preferences, skip the question and apply directly (still show the summary). Otherwise:
Question: "Should I remove these redundant permissions from local files?"
Options:
- "Yes, clean them up"
- "Show me the full list first"
- "Skip cleanup"If user approves:
scripts/discover-settings.sh | scripts/cleanup-redundant.py --applyMark Phase 2 task as completed.
Goal: Everything that requires real user judgment — security risks, policy conflicts, stale cruft, and cleanup opportunities. Present all categories together.
Flag permissions that match these patterns:
High Risk (recommend removal):
Bash(curl *), Bash(wget *) — network exfiltration riskBash(rm *) — can delete any fileBash(source *) — executes arbitrary scriptsBash(eval *) — arbitrary code executionModerate Risk (review):
Bash(git reset *), Bash(git checkout *) — can discard workBash(pkill *), Bash(kill *) — process terminationBash(python *), Bash(python3 *), Bash(node *) — arbitrary code (flag if user hasn't consciously chosen this)Adjust what counts as "moderate" vs "high" based on the user's risk_tolerance preference if set.
Read the user's global ~/.claude/CLAUDE.md for stated tool preferences. Flag local permissions that conflict with those policies.
How to detect: Look for patterns like "prefer X over Y", "use X instead of Y", "avoid Y". Then scan all local permissions for uses of the deprecated tool. For example:
If CLAUDE.md says "prefer tool X over built-in Y", flag all Y permissions across local settings as policy conflicts.Present these as informational — the user may have valid reasons for specific overrides.
Bash(prettier --write /full/path/to/file.md))Bash(done), Bash(for file in *.rs))Bash(cmd:*)) that weren't caught by the cleanup script (e.g., ones without a global equivalent)Read, Write, or Edit permissions for paths outside the projectWrite(~/.config/*) as security concernsmcp__server__*) — convenient but auto-permits any future tools added to that server without reviewAfter cleanup, identify settings files where:
Offer to delete these empty files entirely — they serve no purpose.
## Judgment Calls
### Security Hygiene
#### High Risk — Recommend Removal
| Permission | Project | Risk |
| -------------- | --------- | ----------------- |
| `Bash(curl *)` | project-x | Data exfiltration |
#### Moderate Risk — Review
| Permission | Project | Risk |
| ---------- | ------- | ---- |
| ... | ... | ... |
### Policy Conflicts
| Permission | Projects | Policy |
| --------------- | -------- | --------------------------- |
| `WebFetch(url)` | 3 | CLAUDE.md: prefer Firecrawl |
### One-Off Cruft
| Permission | Project |
| -------------------------------------------------- | --------- |
| `Bash(prettier --write /path/to/specific/file.md)` | project-y |
### External File Access
| Permission | Projects | Notes |
| ------------------------------ | ---------- | ------------------------------- |
| `Write(~/.config/tool/config)` | 3 projects | Shared config — consider global |
| `Edit(/etc/hosts)` | 1 project | System file — review necessity |
### MCP Tool Permissions
| Permission | Projects | Notes |
| -------------------------- | -------- | ------------------------------------------- |
| `mcp__slack__post_message` | 2 | Side effect: sends messages externally |
| `mcp__puppeteer__*` | 1 | Server wildcard — auto-permits future tools |
### Empty Settings Files
| File | Reason |
| ----------------------------------------- | ------------------------------------------ |
| `~/project-z/.claude/settings.local.json` | All permissions removed, no other settings |Use AskUserQuestion:
Question: "How should I handle the judgment call 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 separately.
Edit each affected settings.local.json to remove approved items. Delete empty settings files if approved.
Mark Phase 3 task as completed.
After all phases complete, offer to create or update ~/.claude/cc-maintenance.local.md with session learnings. Include:
Location: ~/.claude/cc-maintenance.local.md
Read at audit start. If missing, proceed with defaults. At session end, offer to create/update.
Format: YAML frontmatter for structured preferences + markdown body for freeform notes.
---
# All preferences are optional
risk_tolerance: moderate # conservative | moderate | aggressive
auto_cleanup_redundant: true
---
## Tool Preferences
- Prefer Exa/Firecrawl over built-in WebSearch/WebFetch
## Risk Notes
- sqlite3 and op item get considered moderate risk
- uv run python treated as arbitrary code execution
## Notes
- Always keep python3 permissions in the data-science project
- Don't consolidate Firecrawl tools into a server wildcard
## Session History
### 2026-02-09
- Promoted 13 permissions to global
- Removed ~220 cruft permissions from Assistant projectBehavior:
risk_tolerance adjusts what gets flagged as moderate vs high in Phase 3auto_cleanup_redundant skips the confirmation prompt in Phase 2 (still shows summary)All scripts are in scripts/ relative to this skill directory.
.claude/settings.local.json files across ~ using fd with sensible exclusions (Library, node_modules, .git, etc.). Max depth of 5 for performance.--apply to modify files.Usage examples:
# Extract and aggregate all permissions
scripts/discover-settings.sh | xargs scripts/extract-permissions.py
# Preview redundant permission cleanup (dry-run, default)
scripts/discover-settings.sh | scripts/cleanup-redundant.py
# Actually remove redundant permissions
scripts/discover-settings.sh | scripts/cleanup-redundant.py --applyUse space-syntax for all permissions: Bash(cmd *) not Bash(cmd:*).
Patterns worth promoting. These operate on local project code or perform read-only operations. Compare against the actual global config, not just this static list — these are examples of the kinds of patterns to look for.
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
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 |
When adding to ~/.claude/settings.json:
Bash(cmd *) not Bash(cmd:*)~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.