Skip to main content

Why Permissions Matter

Agents with unrestricted access can:
  • Execute dangerous commands
  • Modify critical files
  • Access sensitive data
  • Make irreversible changes
Permissions create guardrails that let agents work autonomously while keeping humans in control.

Permission Models

Only explicitly permitted actions are allowed:
{
  "permissions": {
    "allow": [
      "Read(**)",
      "Glob(**)",
      "Grep(**)",
      "Bash(git status:*)",
      "Bash(npm test:*)"
    ]
  }
}

Denylist

Everything allowed except explicitly denied:
{
  "permissions": {
    "deny": [
      "Bash(rm -rf:*)",
      "Bash(sudo:*)",
      "Write(.env)"
    ]
  }
}

Hybrid

Combine both for fine-grained control:
{
  "permissions": {
    "allow": [
      "Bash(git:*)",
      "Bash(npm:*)"
    ],
    "deny": [
      "Bash(git push --force:*)",
      "Bash(npm publish:*)"
    ]
  }
}

Configuration by Tool

File: .claude/settings.json
{
  "permissions": {
    "allow": [
      "Read(**)",
      "Edit(**)",
      "Write(**)",
      "Glob(**)",
      "Grep(**)",
      "Bash(git:*)",
      "Bash(npm:*)",
      "Bash(node:*)"
    ],
    "deny": [
      "Bash(rm -rf:*)",
      "Bash(sudo:*)"
    ]
  }
}

Permission Categories

File Operations

PermissionRisk LevelRecommendation
ReadLowAllow broadly
WriteMediumScope to project
DeleteHighRequire confirmation
ExecuteHighAllowlist only
{
  "permissions": {
    "allow": [
      "Read(**)",
      "Write(src/**)",
      "Write(tests/**)",
      "Edit(src/**)",
      "Edit(tests/**)"
    ],
    "deny": [
      "Write(.env*)",
      "Write(*.pem)",
      "Write(credentials*)"
    ]
  }
}

Shell Commands

CommandRisk LevelNotes
git status/diff/logLowRead-only
git add/commitMediumChanges repo state
git pushHighAffects remote
git push --forceCriticalDestructive
rm -rfCriticalNever allow
sudoCriticalNever allow
{
  "permissions": {
    "allow": [
      "Bash(git status:*)",
      "Bash(git diff:*)",
      "Bash(git log:*)",
      "Bash(git add:*)",
      "Bash(git commit:*)",
      "Bash(npm install:*)",
      "Bash(npm test:*)",
      "Bash(npm run:*)"
    ],
    "deny": [
      "Bash(git push --force:*)",
      "Bash(git reset --hard:*)",
      "Bash(rm -rf:*)",
      "Bash(sudo:*)"
    ]
  }
}

Network Access

{
  "permissions": {
    "allow": [
      "WebFetch(domain:github.com)",
      "WebFetch(domain:docs.anthropic.com)",
      "WebFetch(domain:localhost)"
    ],
    "deny": [
      "WebFetch(domain:*internal*)"
    ]
  }
}

MCP Tools

{
  "permissions": {
    "allow": [
      "mcp__supabase__list_tables",
      "mcp__supabase__execute_sql",
      "mcp__chrome-devtools__take_screenshot"
    ],
    "deny": [
      "mcp__supabase__delete_*",
      "mcp__*__deploy_*"
    ]
  }
}

Permission Patterns

Read-Only Agent

Safe for exploration and analysis:
{
  "permissions": {
    "allow": [
      "Read(**)",
      "Glob(**)",
      "Grep(**)",
      "Bash(git log:*)",
      "Bash(git status:*)",
      "Bash(git diff:*)"
    ]
  }
}

Development Agent

Standard development workflow:
{
  "permissions": {
    "allow": [
      "Read(**)",
      "Write(src/**)",
      "Write(tests/**)",
      "Edit(**)",
      "Glob(**)",
      "Grep(**)",
      "Bash(git:*)",
      "Bash(npm:*)",
      "Bash(node:*)"
    ],
    "deny": [
      "Write(.env*)",
      "Bash(git push --force:*)",
      "Bash(npm publish:*)"
    ]
  }
}

CI/CD Agent

Deployment with safeguards:
{
  "permissions": {
    "allow": [
      "Read(**)",
      "Bash(git:*)",
      "Bash(npm run build:*)",
      "Bash(npm test:*)",
      "Bash(docker build:*)",
      "Bash(gcloud run deploy:*)"
    ],
    "deny": [
      "Write(**)",
      "Edit(**)",
      "Bash(git push --force:*)"
    ]
  }
}

Confirmation Prompts

Require human approval for sensitive actions:
{
  "permissions": {
    "requireConfirmation": [
      "Bash(git push:*)",
      "Bash(npm publish:*)",
      "Write(*.config.*)",
      "mcp__*__deploy_*"
    ]
  }
}

Audit Logging

Track all permission-related events:
{
  "permissions": {
    "audit": {
      "enabled": true,
      "logFile": ".agents/audit.log",
      "logLevel": "all",
      "alertOn": ["denied", "elevated"]
    }
  }
}
Audit log example:
2024-01-15T10:30:00Z [ALLOWED] Read(src/api/auth.ts) agent=code-reviewer
2024-01-15T10:30:05Z [DENIED] Bash(rm -rf node_modules) agent=code-reviewer
2024-01-15T10:30:10Z [CONFIRMED] Bash(git push origin main) agent=deployer user=jorge

Best Practices

  • Start with minimal permissions, expand as needed
  • Use allowlists over denylists
  • Scope file access to project directories
  • Never allow sudo or rm -rf
  • Require confirmation for destructive actions
  • Enable audit logging in production
  • Review permissions when adding new agents
Security risks:
  • Overly permissive defaults
  • Forgotten legacy permissions
  • Permissions copied between environments
  • Missing audit trails
  • No separation between dev/prod permissions