Permission engineering é o eixo mais importante em ambientes profissionais. O time precisa de fluidez (não aprovar git status 40 vezes por dia) e garantias (nunca rodar curl num ambiente corporativo). Em 2026 o Claude Code oferece allowlist granular com patterns, deny rules absolutas por camada, sandbox de rede, reconhecimento de wrappers, auto mode com classifier e /fewer-permission-prompts pra gerar políticas do uso real. Este módulo mostra como construir uma política defensável que não trava ninguém.
Allowlist granular: patterns que cobrem 80% do workflow
// .claude/settings.json — allowlist típica de projeto ativo
{
"permissions": {
"allow": [
// Git read-only (nunca-pergunta)
"Bash(git status)",
"Bash(git status --porcelain)",
"Bash(git diff)",
"Bash(git diff:*)",
"Bash(git log)",
"Bash(git log:*)",
"Bash(git branch)",
"Bash(git branch:*)",
"Bash(git blame:*)",
"Bash(git show:*)",
// Git write-safe
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git stash:*)",
"Bash(git switch:*)",
// NPM/PNPM seguros
"Bash(npm test)",
"Bash(npm test:*)",
"Bash(npm run lint:*)",
"Bash(npm run build)",
"Bash(npm run typecheck)",
"Bash(pnpm:*)",
// File operations
"Read(**)",
"Glob(**)",
"Grep(**)",
"Edit(src/**)",
"Edit(tests/**)",
"Edit(docs/**)",
"Write(src/**)",
"Write(tests/**)",
// Dev tools
"Bash(ls:*)",
"Bash(cat:*)",
"Bash(head:*)",
"Bash(tail:*)",
"Bash(wc:*)",
"Bash(pwd)",
"Bash(which:*)"
],
"ask": [
// Write-risco: pede confirmação sempre
"Bash(git push)",
"Bash(git push:*)",
"Bash(docker:*)",
"Bash(npm install:*)",
"Bash(pnpm install:*)",
"Edit(package.json)",
"Edit(Dockerfile)",
"Edit(.github/**)"
],
"deny": [
// Proibido absoluto
"Bash(rm -rf:*)",
"Bash(sudo:*)",
"Bash(curl:*)",
"Bash(wget:*)",
"Bash(ssh:*)",
"Bash(git push --force:*)",
"Bash(git push -f:*)",
"Bash(git reset --hard:*)",
"Bash(npm publish:*)",
"Bash(terraform apply:*)",
"Edit(.env*)",
"Edit(**/secrets/**)",
"Edit(**/credentials/**)",
"Write(/etc/**)",
"Write(~/.ssh/**)",
"Write(~/.aws/**)",
"Write(~/.gnupg/**)"
]
}
}Padrões de pattern matching
| Pattern | Matcha | Não matcha |
|---|---|---|
| Bash(git status) | "git status" | "git status --porcelain" |
| Bash(git status:*) | "git status", "git status -s", "git status --porcelain" | "git statusfoo" |
| Bash(git:*) | qualquer subcomando git | comandos sem git |
| Bash(npm test:*) | "npm test", "npm test -- --watch" | "npm run test" (diferente!) |
| Read(**) | qualquer path | — |
| Edit(src/**) | "src/a/b.ts" | "tests/a.ts" |
| Edit(src/**/*.ts) | "src/a.ts", "src/a/b.ts" | "src/a.py" |
| Edit(!src/legacy/**) | fora de src/legacy/ | src/legacy/** |
Mudança crítica em 2026: Bash(find:*) NÃO mais auto-aprova find -exec ou -delete — são tratados como ações separadas. Similar: sudo/env/watch/ionice/setsid matchados corretamente como wrappers (não bypass do match do comando inner).
Sandbox de rede: deniedDomains como última linha
// Evita exfiltração mesmo se Claude for enganado por prompt injection
{
"sandbox": {
"network": {
"deniedDomains": [
"pastebin.com",
"transfer.sh",
"ngrok.io",
"*.ngrok.io",
"*.glitch.me",
"webhook.site",
"ipinfo.io",
"*.tunnel.dev"
]
}
}
}
// Qualquer conexão a esses domínios é bloqueada no nível do sandbox,
// independente de Claude ter ou não permissão para Bash(curl:*).
// Camada de defesa em profundidade: deny rules bloqueiam curl;
// sandbox bloqueia o destino mesmo que curl fosse permitido.
// Caso real: dev instala ferramenta suspeita que usa ngrok.io para exfiltrar.
// Mesmo sem saber, sandbox bloqueia a conexão.Permission modes: plan → auto → bypassPermissions
| Modo | Comportamento | Quando usar |
|---|---|---|
| plan | Read-only + planning, nunca edita/executa | Exploração inicial, research |
| default | Pergunta pra ações de risco (padrão) | Dev local seguro |
| acceptEdits | Auto-aprova Edit/Write; pergunta pra Bash | Iteração rápida em feature |
| auto | Classifier decide: pergunta só em alto risco | Dev experiente, projeto conhecido |
| bypassPermissions | Aprova TUDO — sandbox/container only | Docker descartável, nunca local |
# Iniciar com modo específico:
claude --permission-mode plan # exploração
claude --permission-mode acceptEdits # dev de feature
claude --permission-mode auto # dev experiente
# Durante a sessão, Shift+Tab cicla modos
# (só até onde enterprise policy permitir)
# bypassPermissions em sandbox isolado:
docker run --rm -v $(pwd):/workspace anthropic/claude-code \
--permission-mode bypassPermissions \
-p "rode testes e corrija falhas" \
--max-budget-usd 5
# Default para projeto (em settings.json):
{
"defaultMode": "plan"
}
# Dev começa em plan toda vez → segurança por padrão/fewer-permission-prompts: políticas do uso real
# No projeto onde você já usa Claude Code:
/fewer-permission-prompts
# O que acontece:
# 1. Claude Code analisa transcripts históricos (últimas N sessões)
# 2. Identifica comandos que você aprovou consistentemente
# (ex: "git diff" aprovado 47/47 vezes = candidato forte)
# 3. Identifica comandos ocasionalmente aprovados
# (ex: "docker run" aprovado 8/20 = provavelmente NÃO incluir)
# 4. Gera proposta em formato:
{
"permissions": {
"allow": [
"Bash(git status)", // aprovado 47× sem exceção
"Bash(git diff:*)", // aprovado 47× sem exceção
"Bash(npm test:*)", // aprovado 23× sem exceção
"Bash(pnpm:*)", // aprovado 31× sem exceção
"Read(**)", // nunca causou problema
"Glob(**)",
"Grep(**)"
],
"ask": [
"Bash(docker:*)" // às vezes aprovado, às vezes não
]
}
}
# 5. Você revisa, edita, e o Claude Code oferece commitar.
# 6. Próximas sessões: reduction dramática de prompts repetitivos.
# Rodar periodicamente:
# - A cada 2 semanas em projeto ativo
# - Após onboard de nova feature/stack
# - Quando novos padrões se estabilizamEnterprise policy: a camada inviolável
// Managed via SSO/IDP, distribuída automaticamente para todos os devs
// Localização: varia por OS (macOS: /Library/Application Support/ClaudeCode/)
// Devs NÃO podem editar; administração central controla.
{
"permissions": {
"deny": [
"Bash(curl:*)", // nunca egresso HTTP
"Bash(wget:*)",
"Bash(ssh:*)",
"Bash(scp:*)",
"Bash(rsync:*)",
"Bash(nc:*)",
"Bash(netcat:*)",
"Bash(npm publish:*)", // nunca publish em npm
"Bash(pnpm publish:*)",
"Bash(docker push:*)", // nunca push em registry
"Bash(git push --force:*)",
"Bash(git push -f:*)",
"Write(/etc/**)",
"Write(~/.ssh/**)",
"Write(~/.aws/**)",
"Write(~/.kube/**)"
]
},
"sandbox": {
"network": {
"deniedDomains": [
"pastebin.com",
"*.ngrok.io",
"*.tunnel.dev",
"webhook.site",
"transfer.sh"
]
}
},
"disableSkillShellExecution": false, // skills com !`cmd` permitidas
"forceRemoteSettingsRefresh": true // devs não podem cachear policy antiga
}
// Propriedades INVIOLÁVEIS:
// - denies enterprise são aditivos (não sobrescrevíveis)
// - sandbox.network.deniedDomains é ABSOLUTO
// - flags como disableSkillShellExecution vencem níveis inferiores
// Distribuição: admin central push via MDM/GPO/Intune.
// Devs veem via /doctor se estão em compliance.Permission engineering balanceada: allowlist granular para fluidez do dia-a-dia (/fewer-permission-prompts gera do uso real). Deny rules absolutas para guardrails (rm -rf, curl, sudo). Ask para ações com impacto moderado (push, docker). Sandbox.network.deniedDomains para defender contra prompt injection. Enterprise policy como camada inviolável em ambientes regulados. Auto mode com classifier para dev experiente. Plan mode como default para novos projetos. Resultado: time produtivo com compliance garantido.
Próximo: Skills avançadas — o quarto eixo. Skills com pastas completas (scripts/, reference.md), frontmatter rico (allowed-tools, context: fork, agent:, paths), dynamic context injection com !`cmd`, hooks scoped que só rodam durante a skill. A diferença entre scripts glorificados e workflows profissionais.