Como blindar as permissões do Claude Code: bloquear gravações fora do repositório, negar em vez de perguntar e auditar o settings.local.json
Atualizado em

A versão curta: coloque isto em .claude/settings.json na raiz do repositório, faça o commit e reinicie o Claude Code. Exige o Claude Code 2.1.319 ou mais recente (claude --version e depois claude update).
{
"permissions": {
"blockWritesOutsideWorkingDirectories": true,
"denyInsteadOfPrompting": true,
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(curl *)",
"Bash(wget *)"
]
}
}O que cada linha garante para você:
| Linha | O que faz | Adicionado em |
|---|---|---|
blockWritesOutsideWorkingDirectories | As ferramentas Write, Edit e NotebookEdit recusam qualquer caminho fora dos seus diretórios de trabalho, em todos os modos de permissão, inclusive bypassPermissions | 2.1.314 (30 de outubro de 2026) |
denyInsteadOfPrompting | Uma chamada de ferramenta que ficaria aguardando um prompt de permissão é negada e o turno continua, em sessões de terminal, subagentes e teammates | 2.1.319 (6 de novembro de 2026) |
Regras deny de Read(...) | .env e secrets/ continuam ilegíveis para as ferramentas de arquivo e para comandos de shell como cat, head e sed que citam o arquivo | existe há muito tempo |
Bash(curl *) / Bash(wget *) | Downloads pela rede a partir do shell são recusados em vez de gerar uma pergunta | existe há muito tempo |
Testei o bloqueio de gravação, as regras deny e o comportamento em execução sem supervisão no macOS com o Claude Code 2.1.319 em 8 de novembro de 2026, em execuções claude -p --output-format json com o modo de permissão definido por teste. As mensagens exatas de recusa estão citadas abaixo. O changelog (opens in a new tab) descreve denyInsteadOfPrompting para sessões de terminal, subagentes e teammates, que uma execução -p já nega, então sua descrição vem do changelog, não de um teste. O restante deste guia explica por que essas configurações importam agora, o que cada uma cobre e não cobre, e três verificações que você deve rodar uma vez.
Por que agora: três incidentes em nove dias
O Claude Code lançou sete versões entre 26 de outubro e 6 de novembro de 2026, e três histórias de segurança apareceram na mesma janela. Cada uma corresponde a uma verificação concreta.
| Data | O que aconteceu | Sua verificação única |
|---|---|---|
| 30 de out. | A Phorion encontrou uma build com backdoor da extensão oficial Claude Code for VS Code no Cursor Marketplace, versões 2.1.312 e 2.1.313. Ela acrescenta uma chave SSH do atacante em ~/.ssh/authorized_keys e instala persistência (aviso (opens in a new tab), HN, 1.011 pontos (opens in a new tab)) | Liste a versão da sua extensão e faça grep em authorized_keys, veja o passo 5 abaixo |
| 5 de nov. | Issue #107757 (opens in a new tab) do GitHub: o Claude Code colocava o endereço de e-mail da conta no header User-Agent das requisições web. quase 1.000 reações, ainda aberta em 8 de novembro (HN, 1.597 pontos (opens in a new tab)) | Atualize para a 2.1.317 ou mais recente, que pergunta antes de uma ferramenta enviar seu e-mail, veja o passo 6 abaixo |
| 7 de nov. | A Apiiro encontrou 1.122 arquivos públicos no GitHub em que uma aprovação do tipo "Yes, and don't ask again" havia salvado um comando de shell contendo uma senha ou um token em .claude/settings.local.json (relatório (opens in a new tab), HN, 500+ pontos (opens in a new tab)) | Rode o script de auditoria do passo 4 abaixo |
Nenhum desses casos é resolvido por um modo de permissão. Eles exigem um arquivo de configurações, uma auditoria e uma verificação de versão.
- Como blindar as permissões do Claude Code: bloquear gravações fora do repositório, negar em vez de perguntar e auditar o settings.local.json
- Como converter Python em EXE: Runcell, PyInstaller, Nuitka e cx_Freeze
- Como atualizar para o pandas 3.1: inplace obsoleto, df.select() e read_csv mais rápido
- Como atualizar para o OpenCode 2.0: migre config, plugins e sessões da v1
- Como atualizar para o Python 3.15: instalar com uv, usar imports preguiçosos (lazy imports) e checar seus pacotes
- Tutorial de Claude Code Mods: como criar, testar e instalar seu primeiro mod, com 15 exemplos da comunidade
- GPT Image 2.5: como usar, Flare vs Sunburst e preços da API
- Como usar o DeepSeek Harness: instalar, configurar e rodar seu primeiro agente
- Runcell Science: alternativa open source ao Claude Science para pesquisa com IA
- Como impedir o Mac de dormir: mantenha Codex, Claude Code e agentes de IA rodando
- OpenClaw vs ZeroClaw vs Pi Agent vs Nanobot: qual stack de agentes de IA você deve escolher em 2026?
- Como o Claude Code analisa notebooks Jupyter em Data Science: capacidade real, limites e alternativa melhor
- Claude Code Routines: rotinas e cron jobs para agentes de IA
- Claude Code Desktop: como ativar Bypass permissions
- Como Construir Dois Agentes Python com o Protocolo A2A do Google - Tutorial Passo a Passo
- Top 10 bibliotecas de visualização de dados em Python em 2025
Passo 1: bloquear gravações de arquivo fora do repositório
permissions.blockWritesOutsideWorkingDirectories faz as três ferramentas de edição de arquivo recusarem qualquer caminho que não esteja dentro de um diretório de trabalho. Os diretórios de trabalho são a pasta em que você iniciou o Claude Code mais qualquer coisa que você tenha adicionado com /add-dir, --add-dir ou permissions.additionalDirectories nas suas configurações de usuário ou gerenciadas. Uma entrada additionalDirectories no .claude/settings.json do próprio repositório não remove o bloqueio. O bloqueio vale em todos os modos de permissão, inclusive bypassPermissions, e um true em qualquer arquivo de configurações vence um false em outro lugar, então um repositório pode ativá-lo para todo mundo que o clonar.
Defini a chave em um projeto de teste e pedi ao Claude Code, no modo acceptEdits, para criar um arquivo no meu diretório home com a ferramenta Write. A chamada foi recusada com esta mensagem:
/Users/me/kanaries-block-test.txt is outside /path/to/proj; the
permissions.blockWritesOutsideWorkingDirectories setting blocks writes
outside the working directories. Ask the user to add the directory with
/add-dir, or to remove that setting.O arquivo não foi criado, e o resultado em JSON listou a chamada em permission_denials com tool_name: "Write".
Quatro limites que você precisa conhecer antes de confiar nisso:
- Ele não limita comandos de shell, ferramentas MCP nem programas de hook.
echo x > ~/filepela ferramenta Bash não é uma chamada deWrite. Para cercar gravações feitas pelo shell, ative o sandbox (veja a seção opcional no fim deste guia). - Alguns arquivos do próprio Claude Code continuam graváveis: arquivos de plano, o scratchpad da sessão, o diretório
tmpde uma sessão em segundo plano e os arquivos.mdda memória automática do projeto. Isso é intencional. - O Claude não consegue mais editar nenhum arquivo de configurações do Claude Code, nem mesmo dentro do repositório, porque um arquivo de configurações poderia remover o bloqueio. Edite o
.claude/settings.jsonvocê mesmo. - As ferramentas de worktree desaparecem. Com a chave ativada, o Claude Code remove
EnterWorktreeeExitWorktreeou recusa chamadas a elas. Se os subagentes precisarem de worktrees, adicione.claude/worktreesna raiz do repositório como diretório de trabalho.
A configuração irmã, permissions.blockReadsOutsideWorkingDirectories (2.1.257 ou mais recente), faz o mesmo para Read, Grep, Glob e chamadas LSP. Ative-a quando o repositório não deve enxergar o resto do seu disco.
Passo 2: manter segredos ilegíveis com regras deny
Uma regra deny Read(path) bloqueia as ferramentas de arquivo embutidas e, segundo a documentação, os comandos de arquivo que o Claude Code reconhece no Bash (cat, head, tail, sed, tee), além de redirecionamentos de shell que citam o arquivo. Ela também bloqueia Edit e Write no mesmo caminho, então o Claude também não consegue sobrescrever o seu .env.
Testado: com "deny": ["Read(./.env)"], pedir ao Claude para ler o .env com a ferramenta Read retornou:
File is in a directory that is denied by your permission settings.A regra alcança o shell também. Em uma execução em acceptEdits, pedi cat README.md e depois cat .env: o primeiro imprimiu o arquivo, o segundo foi recusado com Permission to use Bash with command cat .env has been denied. Uma execução separada de claude -p no modo padrão recusou curl -sI https://example.com por causa da regra Bash(curl *). Cada negação foi registrada em permission_denials, e cada execução terminou em vez de travar.
Três armadilhas de sintaxe de regras, da referência de permissões (opens in a new tab):
- Use
Read(...)eEdit(...). RegrasWrite(docs/**),Grep(docs/**)eGlob(...)com um caminho são aceitas, mas nunca casam com nada. Bash(git diff *), com espaço antes do*, casa com qualquer comando que comece comgit diff.Bash(git diff*)também casaria comgit diff-index.- Uma regra deny não pega um comando que lê um arquivo sem citá-lo, como
grep -r pattern .executado a partir da pasta que contém o segredo. É para isso que serve o sandbox.
Um arquivo .claudeignore não tem efeito nenhum. Mova as entradas dele para regras deny de Read.
Passo 3: nunca travar em um prompt de permissão
Agora existem quatro maneiras de fazer uma execução sem supervisão do Claude Code negar em vez de esperar. Escolha de acordo com onde a execução acontece.
| Situação | Use | Comportamento |
|---|---|---|
| Sessão interativa de terminal da qual você se afasta, incluindo seus subagentes e teammates | "denyInsteadOfPrompting": true nas configurações (2.1.319) | Uma chamada que ficaria aguardando um prompt é negada e o turno continua (texto do changelog; não consegui testar isso no modo -p porque o -p já nega) |
Execução de claude -p ou do Agent SDK sem modo de permissão definido | Nada a mais | Desde a 2.1.302, o -p inicia no modo Manual e nega qualquer chamada que precise de aprovação. Testado acima |
| Job de CI trancado | --permission-mode dontAsk | Toda chamada que geraria um prompt é negada (um mod que você instalou ainda pode aprovar algumas chamadas). Comandos somente leitura, leituras de arquivo dentro dos diretórios de trabalho e suas regras allow continuam funcionando |
Execução com um host de permissões, como um app do SDK com canUseTool ou --permission-prompt-tool | --permission-prompts none (2.1.259 ou mais recente) | A execução não espera pelo host; o Claude é avisado de que ninguém pode aprovar e de que não deve tentar de novo |
Testado com --permission-mode dontAsk --permission-prompts none: python3 -c 'print(2+2)' foi negado com uma mensagem que começa com Permission to use Bash has been denied because Claude Code is running in don't ask mode, enquanto git log --oneline -1 rodou porque está na lista embutida de comandos somente leitura. O JSON de resultado trouxe uma entrada em permission_denials.
Coisas que nenhum modo e nenhuma regra allow conseguem aprovar, nem mesmo bypassPermissions: regras ask explícitas, a ferramenta AskUserQuestion, ferramentas MCP marcadas com requiresUserInteraction, e comandos rm reconhecidos como de caminho crítico, como rm -rf ~. O dontAsk nega todas elas de imediato, e também nega leituras de caminhos de rede mesmo quando uma regra allow casa.
Se um repositório nunca deve rodar em modo bypass, adicione "disableBypassPermissionsMode": "disable" dentro de permissions. O Claude Code então rejeita --dangerously-skip-permissions e ignora uma definição de subagente que peça bypass.
Passo 4: auditar o settings.local.json em busca de regras allow vazadas
Este é o mecanismo por trás do relatório da Apiiro. Quando o Claude pede para rodar um comando de shell e você escolhe Yes, and don't ask again, o Claude Code salva uma regra allow com aquele prefixo de comando em .claude/settings.local.json na raiz do repositório. Se o comando era psql postgres://app:Sup3rSecret@db/prod -c ..., a senha agora está na regra.
O Claude Code adiciona **/.claude/settings.local.json ao seu arquivo global de excludes do git na primeira vez em que grava o arquivo em um repositório que ainda não o ignora. No meu Mac esse arquivo é ~/.config/git/ignore, e o padrão está na linha 1. É por isso que git add .claude/settings.local.json falha aqui com "ignored by one of your .gitignore files". Mas a proteção é por máquina, não por repositório. Um arquivo que você criou à mão antes de o Claude Code gravar nele, um repositório copiado para outra máquina como diretório em vez de clonado, ou um sandbox sem os seus excludes globais: todos fazem commit do arquivo como qualquer outro. O autor do relatório da Apiiro disse no HN que, em 539 dos 1.105 repositórios rastreados, um commit coautorado pelo Claude alterou o arquivo.
Rode isto a partir da raiz do repositório. O script encontra todo .claude/settings*.json, informa se o git o rastreia e marca regras allow que carregam credenciais ou aprovam famílias inteiras de ferramentas.
cat > /tmp/claude-settings-audit.sh <<'EOF'
#!/usr/bin/env bash
set -u
root="${1:-.}"
found=0
while IFS= read -r -d '' f; do
found=1
echo "== $f"
if git -C "$(dirname "$f")" ls-files --error-unmatch "$(basename "$f")" >/dev/null 2>&1; then
echo " TRACKED BY GIT <- settings.local.json should never be"
fi
grep -nE '"(Bash|PowerShell)\([^"]*(password|passwd|token|secret|api[_-]?key|Authorization|Bearer |PGPASSWORD|AWS_SECRET|--password|://[^"/]*:[^"@]*@|[A-Z_]{3,}=[^[:space:]"]{8,})' "$f" \
| sed 's/^/ SECRET-LIKE: /'
grep -nE '"(Bash|PowerShell)(\(\*\))?"|"Bash\((sudo|rm|curl|wget|ssh|scp|git push|npm publish|docker)[^"]*\*\)"' "$f" \
| sed 's/^/ BROAD: /'
done < <(find "$root" -path '*/node_modules' -prune -o -type f \
\( -name 'settings.local.json' -o -name 'settings.json' \) -path '*/.claude/*' -print0 2>/dev/null)
[ "$found" = 0 ] && echo "No .claude/settings*.json under $root"
EOF
bash /tmp/claude-settings-audit.sh .Em um arquivo sintético com seis regras, ele marcou as três que embutiam uma senha de banco de dados, um bearer token e uma atribuição DATABASE_URL=..., além de Bash(*), Bash(rm -rf *) e, uma segunda vez, a regra curl sob BROAD. Quando o arquivo foi commitado em um repositório de teste, ele também imprimiu a linha TRACKED BY GIT. É um grep, então conte em ler os resultados por conta própria.
O que fazer com um resultado positivo:
- Rotacione a credencial primeiro. Se o arquivo já foi enviado para o remoto alguma vez, trate o segredo como público. Reescrever o histórico não basta depois que um fork ou um scraper já o capturou.
- Apague a regra, ou substitua por uma que não carregue o segredo: aprove
psql *e passe a senha porPGPASSWORDa partir do ambiente do seu shell, não dentro do comando. - Se o git rastreia o arquivo, rode
git rm --cached .claude/settings.local.jsone adicione.claude/settings.local.jsonao.gitignoredo repositório, para que a proteção viaje com o repositório em vez de depender dos excludes globais de cada máquina. - Verifique o
.claude/settings.jsontambém. Ele foi feito para ser commitado, então uma regra allow com um segredo ali é um vazamento por design, não por acidente.
Pelo mesmo motivo, prefira regras deny e ask no arquivo commitado e mantenha as regras allow pessoais no arquivo local. Regras deny e ask valem imediatamente; regras allow vindas de um repositório só valem depois que cada colega confia na pasta.
Passo 5: verificar sua extensão de IDE e suas chaves SSH
As builds com backdoor eram as versões 2.1.312 e 2.1.313 da extensão Claude Code for VS Code distribuída pelo Cursor Marketplace, reportadas pela Phorion em 30 de outubro. A Cursor as removeu. Segundo a Phorion, o payload roda assim que o módulo da extensão é carregado, acrescenta uma chave Ed25519 com o comentário svc-telemetry em ~/.ssh/authorized_keys, tenta ativar o Remote Login e envia informações do host para um servidor. No macOS, a etapa de ativar o SSH falha para um usuário sem privilégios de administrador por causa de um bug no implante, mas a chave e a persistência são instaladas mesmo assim.
Liste as versões instaladas:
cursor --list-extensions --show-versions | grep -i claude
code --list-extensions --show-versions | grep -i claude
ls ~/.cursor/extensions ~/.vscode/extensions 2>/dev/null | grep -i claudeNa minha máquina isso retornou anthropic.claude-code@2.1.302, que está fora do intervalo afetado. Em seguida, verifique o indicador que a Phorion publicou:
grep -n "svc-telemetry" ~/.ssh/authorized_keys 2>/dev/null || echo "no match"A Phorion observa que a string do comentário é controlada pelo atacante, então um grep limpo não é prova. Se você rodou a 2.1.312 ou a 2.1.313 vindas do Cursor Marketplace, remova toda chave que não reconhecer do authorized_keys, revise os itens de login e os launch agents, e trate a máquina como comprometida até que uma resposta a incidentes a tenha examinado. Instale a extensão pelo VS Code Marketplace ou deixe a CLI claude instalá-la via /ide; desde a 2.1.318 o Claude Code não instala nem atualiza mais a extensão por conta própria a partir de um terminal de IDE.
Passo 6: a correção do e-mail no User-Agent
A issue #107757 relata que o Claude Code enviava o endereço de e-mail da conta no header User-Agent das requisições web feitas durante buscas e fetches, de modo que sites e rastreadores podiam coletá-lo. A entrada do changelog da 2.1.317, datada de 3 de novembro, diz: "Added a check that asks before a web or shell tool call sends your account email address to the network." Quem reportou abriu a issue na 2.1.318, e ela ainda estava aberta com quase 1.000 reações em 8 de novembro, então acompanhe para ver a resolução final.
O que você pode fazer hoje: atualizar (claude update) e, se roda sem supervisão, saber que com denyInsteadOfPrompting ou dontAsk essa nova verificação do tipo "pergunta antes" vira uma negação, que é o comportamento que você quer.
O que cada proteção impede: testado vs. documentado
| Tentativa | blockWrites… | Regra deny de Read | Deny Bash(curl *) | dontAsk / padrão do -p | Sandbox |
|---|---|---|---|---|---|
Ferramenta Write cria ~/x.txt | Recusado (testado) | — | — | Prompt → negado | Permitido pelo sandbox, as ferramentas de arquivo ficam fora dele |
Ferramenta Read lê .env | — | Recusado (testado) | — | Permitido, leituras não precisam de aprovação | — |
cat .env no Bash | — | Recusado (testado) | — | Negado | — |
echo x > ~/x.txt no Bash | Não coberto | — | — | Prompt → negado | Bloqueado (docs: Operation not permitted no macOS) |
curl https://… no Bash | — | — | Recusado (testado) | Negado | Bloqueado, a menos que o host esteja na lista permitida |
python3 -c … no Bash | — | — | — | Negado (testado) | Roda dentro do sandbox |
git log, ls, outros comandos somente leitura | — | — | — | Roda (testado) | Roda |
rm -rf ~ | — | — | — | Negado, nenhuma regra consegue aprovar | Bloqueado, o home está fora do conjunto gravável (docs) |
"Testado" significa que eu rodei na 2.1.319 em 8 de novembro de 2026. Todo o resto vem da documentação oficial linkada neste guia.
Opcional: colocar o shell no sandbox também
As configurações acima cercam as ferramentas de arquivo do próprio Claude. Os comandos de shell são cercados pelo sandbox do Bash (opens in a new tab), que vem desativado por padrão. Ele usa o Seatbelt do macOS e, no Linux ou no WSL2, precisa de bubblewrap e socat. Ative-o para um projeto com /sandbox dentro de uma sessão, ou para todos os projetos adicionando a ~/.claude/settings.json:
{
"sandbox": {
"enabled": true
}
}Para confirmar que está funcionando, peça ao Claude para rodar touch ~/sandbox-probe. Dentro do sandbox, o comando falha com Operation not permitted no macOS ou Read-only file system no Linux. Se o Claude oferecer para repetir o comando fora do sandbox, recuse.
Uma configuração combinada cobre a lacuna da matriz acima: ferramentas de arquivo cercadas por blockWritesOutsideWorkingDirectories, shell cercado pelo sandbox, segredos cercados por regras deny de Read e execuções sem supervisão cercadas por denyInsteadOfPrompting. O modo bypass então só acelera os prompts que sobram. Se você ainda precisar de bypass para uma tarefa contida, o guia de bypass permissions cobre o botão e suas mensagens de erro.
FAQ
Guias relacionados
- Claude Code Desktop: como ativar Bypass permissions
- Tutorial de Claude Code Mods: como criar, testar e instalar seu primeiro mod
- Claude Code Routines: rotinas e cron jobs para agentes de IA
- Parallel Code Agents explicados: worktrees, sandboxes e padrões de ferramentas desktop
- Como atualizar para o OpenCode 2.0: migre config, plugins e sessões da v1