[{"data":1,"prerenderedAt":2431},["ShallowReactive",2],{"blog-/blog/claude-code-seguranca-configuracoes-que-protegem-seu-codigo":3},{"id":4,"title":5,"body":6,"date":2418,"description":2419,"extension":2420,"meta":2421,"navigation":812,"path":2422,"seo":2423,"stem":2424,"tags":2425,"__hash__":2430},"blog/blog/claude-code-seguranca-configuracoes-que-protegem-seu-codigo.md","Claude Code: as configurações de segurança que protegem seu código de si mesmo",{"type":7,"value":8,"toc":2400},"minimark",[9,21,33,36,41,44,55,65,75,81,85,100,247,267,271,280,286,343,364,368,371,454,468,472,481,544,563,569,603,606,610,621,636,738,749,754,978,981,991,995,1106,1110,1127,1240,1244,1251,1340,1344,1632,1648,1652,2200,2215,2224,2233,2237,2245,2286,2293,2298,2302,2305,2336,2339,2342,2346,2349,2387,2393,2396],[10,11,12,13,20],"p",{},"A maior parte do que vou explicar aqui veio do ",[14,15,19],"a",{"href":16,"rel":17},"https://anthropic.skilljar.com/claude-code-in-action",[18],"nofollow","curso oficial da Anthropic sobre Claude Code",". Recomendo pra quem quer entender o ferramental completo. O que fiz foi aplicar no meu workflow e adicionar camadas extras de proteção que fazem sentido pro meu contexto.",[10,22,23,24,28,29,32],{},"No artigo anterior, falei sobre como usar skills pra transformar o Claude Code num auditor de segurança. Mas tem um problema anterior a isso: o próprio Claude Code tem acesso ao seu sistema de arquivos. Ele lê arquivos, executa comandos, escreve código. Se não estiver configurado direito, ele pode ler seu ",[25,26,27],"code",{},".env",", exibir suas chaves de API no output, ou rodar um ",[25,30,31],{},"rm -rf"," sem pensar duas vezes.",[10,34,35],{},"A segurança do código que o Claude Code audita não adianta nada se o ambiente onde ele roda não for seguro.",[37,38,40],"h2",{"id":39},"as-três-raízes-de-configuração","As três raízes de configuração",[10,42,43],{},"O Claude Code lê configurações de três lugares, em ordem de prioridade:",[10,45,46,54],{},[47,48,49,50,53],"strong",{},"1. ",[25,51,52],{},"~/.claude/settings.json"," (global)"," — Vale pra todos os projetos. É onde ficam regras pessoais: permissões padrão, hooks globais, preferências de workflow. Fica na home e não é versionado.",[10,56,57,64],{},[47,58,59,60,63],{},"2. ",[25,61,62],{},".claude/settings.json"," (projeto)"," — Fica na raiz do repositório. Sobrescreve o global. É onde ficam regras específicas do projeto: deny rules pra arquivos sensíveis daquele repo, hooks de validação, restrições de time. Versione no git. Assim todos que trabalham no repositório herdam as mesmas restrições.",[10,66,67,74],{},[47,68,69,70,73],{},"3. ",[25,71,72],{},"CLAUDE.md"," (instruções em linguagem natural)"," — Também na raiz do repositório. Não é um JSON de permissões. São instruções em markdown que o Claude Code absorve no início de cada sessão. Regras de estilo, convenções de código, e sim, regras de segurança.",[10,76,77,78,80],{},"A hierarquia funciona assim: o global define o baseline. O projeto restringe ou ajusta. O ",[25,79,72],{}," complementa com contexto semântico que o JSON não consegue expressar.",[37,82,84],{"id":83},"permissions-allow-e-deny","Permissions: allow e deny",[10,86,87,88,91,92,95,96,99],{},"A estrutura principal é o campo ",[25,89,90],{},"permissions",", com duas listas: ",[25,93,94],{},"allow"," e ",[25,97,98],{},"deny",".",[101,102,107],"pre",{"className":103,"code":104,"language":105,"meta":106,"style":106},"language-json shiki shiki-themes github-light github-dark","{\n  \"permissions\": {\n    \"allow\": [\n      \"Bash(*)\",\n      \"Read(*)\",\n      \"Edit(*)\",\n      \"Write(*)\",\n      \"Glob(*)\",\n      \"Grep(*)\"\n    ],\n    \"deny\": [\n      \"Read(./.env)\",\n      \"Read(./.env.*)\",\n      \"Read(./secrets/**)\",\n      \"Read(./config/credentials.json)\"\n    ]\n  }\n}\n","json","",[25,108,109,118,128,137,147,155,163,171,179,185,191,199,207,215,223,229,235,241],{"__ignoreMap":106},[110,111,114],"span",{"class":112,"line":113},"line",1,[110,115,117],{"class":116},"sVt8B","{\n",[110,119,121,125],{"class":112,"line":120},2,[110,122,124],{"class":123},"sj4cs","  \"permissions\"",[110,126,127],{"class":116},": {\n",[110,129,131,134],{"class":112,"line":130},3,[110,132,133],{"class":123},"    \"allow\"",[110,135,136],{"class":116},": [\n",[110,138,140,144],{"class":112,"line":139},4,[110,141,143],{"class":142},"sZZnC","      \"Bash(*)\"",[110,145,146],{"class":116},",\n",[110,148,150,153],{"class":112,"line":149},5,[110,151,152],{"class":142},"      \"Read(*)\"",[110,154,146],{"class":116},[110,156,158,161],{"class":112,"line":157},6,[110,159,160],{"class":142},"      \"Edit(*)\"",[110,162,146],{"class":116},[110,164,166,169],{"class":112,"line":165},7,[110,167,168],{"class":142},"      \"Write(*)\"",[110,170,146],{"class":116},[110,172,174,177],{"class":112,"line":173},8,[110,175,176],{"class":142},"      \"Glob(*)\"",[110,178,146],{"class":116},[110,180,182],{"class":112,"line":181},9,[110,183,184],{"class":142},"      \"Grep(*)\"\n",[110,186,188],{"class":112,"line":187},10,[110,189,190],{"class":116},"    ],\n",[110,192,194,197],{"class":112,"line":193},11,[110,195,196],{"class":123},"    \"deny\"",[110,198,136],{"class":116},[110,200,202,205],{"class":112,"line":201},12,[110,203,204],{"class":142},"      \"Read(./.env)\"",[110,206,146],{"class":116},[110,208,210,213],{"class":112,"line":209},13,[110,211,212],{"class":142},"      \"Read(./.env.*)\"",[110,214,146],{"class":116},[110,216,218,221],{"class":112,"line":217},14,[110,219,220],{"class":142},"      \"Read(./secrets/**)\"",[110,222,146],{"class":116},[110,224,226],{"class":112,"line":225},15,[110,227,228],{"class":142},"      \"Read(./config/credentials.json)\"\n",[110,230,232],{"class":112,"line":231},16,[110,233,234],{"class":116},"    ]\n",[110,236,238],{"class":112,"line":237},17,[110,239,240],{"class":116},"  }\n",[110,242,244],{"class":112,"line":243},18,[110,245,246],{"class":116},"}\n",[10,248,249,250,252,253,255,256,259,260,263,264,266],{},"O ",[25,251,94],{}," define o que o Claude Code pode fazer sem pedir confirmação. O ",[25,254,98],{}," bloqueia absolutamente. Deny sempre ganha de allow. Não importa se o allow tem ",[25,257,258],{},"Read(*)",". Se o deny tem ",[25,261,262],{},"Read(./.env)",", o ",[25,265,27],{}," não é lido.",[37,268,270],{"id":269},"protegendo-variáveis-de-ambiente","Protegendo variáveis de ambiente",[10,272,273,274,276,277,279],{},"O cenário mais comum: o Claude Code precisa ler seu código pra entender o projeto, mas o ",[25,275,27],{}," tem chaves de banco de dados, tokens de API, secrets de autenticação. Se ele ler o ",[25,278,27],{}," e depois for escrever um teste ou documentar algo, aquelas chaves podem aparecer no output, no código gerado, ou pior, num commit.",[10,281,282,283,285],{},"Mas bloquear só a leitura não basta. O Claude Code também pode sobrescrever um ",[25,284,27],{}," existente ou criar um novo com valores errados. As deny rules precisam cobrir as três operações: Read, Write e Edit.",[101,287,289],{"className":103,"code":288,"language":105,"meta":106,"style":106},"\"deny\": [\n  \"Read(./.env)\",\n  \"Read(./.env.*)\",\n  \"Write(./.env)\",\n  \"Write(./.env.*)\",\n  \"Edit(./.env)\",\n  \"Edit(./.env.*)\"\n]\n",[25,290,291,298,305,312,319,326,333,338],{"__ignoreMap":106},[110,292,293,296],{"class":112,"line":113},[110,294,295],{"class":142},"\"deny\"",[110,297,136],{"class":116},[110,299,300,303],{"class":112,"line":120},[110,301,302],{"class":142},"  \"Read(./.env)\"",[110,304,146],{"class":116},[110,306,307,310],{"class":112,"line":130},[110,308,309],{"class":142},"  \"Read(./.env.*)\"",[110,311,146],{"class":116},[110,313,314,317],{"class":112,"line":139},[110,315,316],{"class":142},"  \"Write(./.env)\"",[110,318,146],{"class":116},[110,320,321,324],{"class":112,"line":149},[110,322,323],{"class":142},"  \"Write(./.env.*)\"",[110,325,146],{"class":116},[110,327,328,331],{"class":112,"line":157},[110,329,330],{"class":142},"  \"Edit(./.env)\"",[110,332,146],{"class":116},[110,334,335],{"class":112,"line":165},[110,336,337],{"class":142},"  \"Edit(./.env.*)\"\n",[110,339,340],{"class":112,"line":173},[110,341,342],{"class":116},"]\n",[10,344,345,346,349,350,353,354,353,357,353,360,363],{},"O padrão ",[25,347,348],{},".env.*"," cobre ",[25,351,352],{},".env.local",", ",[25,355,356],{},".env.production",[25,358,359],{},".env.staging",[25,361,362],{},".env.development",". Mas se preferir ser explícito, liste cada um. Explícito é mais seguro que glob quando se trata de secrets.",[37,365,367],{"id":366},"protegendo-diretórios-de-secrets","Protegendo diretórios de secrets",[10,369,370],{},"Muitos projetos mantêm certificados, chaves privadas ou arquivos de credenciais em diretórios dedicados. A mesma lógica: bloquear Read, Write e Edit.",[101,372,374],{"className":103,"code":373,"language":105,"meta":106,"style":106},"\"deny\": [\n  \"Read(./secrets/**)\",\n  \"Write(./secrets/**)\",\n  \"Edit(./secrets/**)\",\n  \"Read(./config/credentials.json)\",\n  \"Write(./config/credentials.json)\",\n  \"Edit(./config/credentials.json)\",\n  \"Read(./**/*.pem)\",\n  \"Read(./**/*.key)\",\n  \"Read(./**/*serviceAccountKey*)\",\n  \"Read(./**/credentials*.json)\"\n]\n",[25,375,376,382,389,396,403,410,417,424,431,438,445,450],{"__ignoreMap":106},[110,377,378,380],{"class":112,"line":113},[110,379,295],{"class":142},[110,381,136],{"class":116},[110,383,384,387],{"class":112,"line":120},[110,385,386],{"class":142},"  \"Read(./secrets/**)\"",[110,388,146],{"class":116},[110,390,391,394],{"class":112,"line":130},[110,392,393],{"class":142},"  \"Write(./secrets/**)\"",[110,395,146],{"class":116},[110,397,398,401],{"class":112,"line":139},[110,399,400],{"class":142},"  \"Edit(./secrets/**)\"",[110,402,146],{"class":116},[110,404,405,408],{"class":112,"line":149},[110,406,407],{"class":142},"  \"Read(./config/credentials.json)\"",[110,409,146],{"class":116},[110,411,412,415],{"class":112,"line":157},[110,413,414],{"class":142},"  \"Write(./config/credentials.json)\"",[110,416,146],{"class":116},[110,418,419,422],{"class":112,"line":165},[110,420,421],{"class":142},"  \"Edit(./config/credentials.json)\"",[110,423,146],{"class":116},[110,425,426,429],{"class":112,"line":173},[110,427,428],{"class":142},"  \"Read(./**/*.pem)\"",[110,430,146],{"class":116},[110,432,433,436],{"class":112,"line":181},[110,434,435],{"class":142},"  \"Read(./**/*.key)\"",[110,437,146],{"class":116},[110,439,440,443],{"class":112,"line":187},[110,441,442],{"class":142},"  \"Read(./**/*serviceAccountKey*)\"",[110,444,146],{"class":116},[110,446,447],{"class":112,"line":193},[110,448,449],{"class":142},"  \"Read(./**/credentials*.json)\"\n",[110,451,452],{"class":112,"line":201},[110,453,342],{"class":116},[10,455,249,456,459,460,463,464,467],{},[25,457,458],{},"**"," faz match recursivo. ",[25,461,462],{},"Read(./**/*.pem)"," bloqueia qualquer arquivo ",[25,465,466],{},".pem"," em qualquer subdiretório. Assim, mesmo que alguém adicione um certificado numa pasta inesperada, o Claude Code não lê.",[37,469,471],{"id":470},"bloqueando-comandos-destrutivos","Bloqueando comandos destrutivos",[10,473,249,474,476,477,480],{},[25,475,94],{}," para Bash aceita glob patterns no argumento. Em vez de ",[25,478,479],{},"Bash(*)",", que permite qualquer comando, é possível ser mais restritivo:",[101,482,484],{"className":103,"code":483,"language":105,"meta":106,"style":106},"\"allow\": [\n  \"Bash(npm test*)\",\n  \"Bash(npm run*)\",\n  \"Bash(git status*)\",\n  \"Bash(git diff*)\",\n  \"Bash(git log*)\",\n  \"Bash(ls*)\",\n  \"Bash(cat package.json)\"\n]\n",[25,485,486,493,500,507,514,521,528,535,540],{"__ignoreMap":106},[110,487,488,491],{"class":112,"line":113},[110,489,490],{"class":142},"\"allow\"",[110,492,136],{"class":116},[110,494,495,498],{"class":112,"line":120},[110,496,497],{"class":142},"  \"Bash(npm test*)\"",[110,499,146],{"class":116},[110,501,502,505],{"class":112,"line":130},[110,503,504],{"class":142},"  \"Bash(npm run*)\"",[110,506,146],{"class":116},[110,508,509,512],{"class":112,"line":139},[110,510,511],{"class":142},"  \"Bash(git status*)\"",[110,513,146],{"class":116},[110,515,516,519],{"class":112,"line":149},[110,517,518],{"class":142},"  \"Bash(git diff*)\"",[110,520,146],{"class":116},[110,522,523,526],{"class":112,"line":157},[110,524,525],{"class":142},"  \"Bash(git log*)\"",[110,527,146],{"class":116},[110,529,530,533],{"class":112,"line":165},[110,531,532],{"class":142},"  \"Bash(ls*)\"",[110,534,146],{"class":116},[110,536,537],{"class":112,"line":173},[110,538,539],{"class":142},"  \"Bash(cat package.json)\"\n",[110,541,542],{"class":112,"line":181},[110,543,342],{"class":116},[10,545,546,547,549,550,353,553,353,556,353,559,562],{},"Sem o ",[25,548,479],{},", qualquer comando que não esteja na lista de allow vai pedir confirmação antes de executar. Isso significa que ",[25,551,552],{},"rm",[25,554,555],{},"curl",[25,557,558],{},"docker",[25,560,561],{},"kubectl"," e qualquer outro comando potencialmente destrutivo precisa de aprovação explícita.",[10,564,565,566,568],{},"Mesmo com ",[25,567,479],{}," liberado, o deny pode bloquear comandos específicos:",[101,570,572],{"className":103,"code":571,"language":105,"meta":106,"style":106},"\"deny\": [\n  \"Bash(rm -rf *)\",\n  \"Bash(git push --force*)\",\n  \"Bash(git reset --hard*)\"\n]\n",[25,573,574,580,587,594,599],{"__ignoreMap":106},[110,575,576,578],{"class":112,"line":113},[110,577,295],{"class":142},[110,579,136],{"class":116},[110,581,582,585],{"class":112,"line":120},[110,583,584],{"class":142},"  \"Bash(rm -rf *)\"",[110,586,146],{"class":116},[110,588,589,592],{"class":112,"line":130},[110,590,591],{"class":142},"  \"Bash(git push --force*)\"",[110,593,146],{"class":116},[110,595,596],{"class":112,"line":139},[110,597,598],{"class":142},"  \"Bash(git reset --hard*)\"\n",[110,600,601],{"class":112,"line":149},[110,602,342],{"class":116},[10,604,605],{},"Essa é a abordagem que faz mais sentido pra quem já tem experiência. Liberar tudo e bloquear o que é perigoso.",[37,607,609],{"id":608},"hooks-a-segunda-camada-de-proteção","Hooks: a segunda camada de proteção",[10,611,612,613,616,617,620],{},"Deny rules protegem por ",[47,614,615],{},"path"," e por ",[47,618,619],{},"comando",". Mas e se o Claude Code ler um secret de outra fonte (um log, um output de comando, uma resposta de API) e tentar escrevê-lo num arquivo de código? O deny por path não pega isso. O hook pega.",[10,622,623,624,627,628,631,632,635],{},"Hooks são scripts que rodam automaticamente antes ou depois de ações do Claude Code. O formato no ",[25,625,626],{},"settings.json"," usa ",[25,629,630],{},"matcher"," pra filtrar a ferramenta e ",[25,633,634],{},"hooks"," como array de handlers:",[101,637,639],{"className":103,"code":638,"language":105,"meta":106,"style":106},"{\n  \"hooks\": {\n    \"PreToolUse\": [\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.claude/hooks/meu-script.sh\"\n          }\n        ]\n      }\n    ]\n  }\n}\n",[25,640,641,645,652,659,664,677,684,689,701,711,716,721,726,730,734],{"__ignoreMap":106},[110,642,643],{"class":112,"line":113},[110,644,117],{"class":116},[110,646,647,650],{"class":112,"line":120},[110,648,649],{"class":123},"  \"hooks\"",[110,651,127],{"class":116},[110,653,654,657],{"class":112,"line":130},[110,655,656],{"class":123},"    \"PreToolUse\"",[110,658,136],{"class":116},[110,660,661],{"class":112,"line":139},[110,662,663],{"class":116},"      {\n",[110,665,666,669,672,675],{"class":112,"line":149},[110,667,668],{"class":123},"        \"matcher\"",[110,670,671],{"class":116},": ",[110,673,674],{"class":142},"\"Bash\"",[110,676,146],{"class":116},[110,678,679,682],{"class":112,"line":157},[110,680,681],{"class":123},"        \"hooks\"",[110,683,136],{"class":116},[110,685,686],{"class":112,"line":165},[110,687,688],{"class":116},"          {\n",[110,690,691,694,696,699],{"class":112,"line":173},[110,692,693],{"class":123},"            \"type\"",[110,695,671],{"class":116},[110,697,698],{"class":142},"\"command\"",[110,700,146],{"class":116},[110,702,703,706,708],{"class":112,"line":181},[110,704,705],{"class":123},"            \"command\"",[110,707,671],{"class":116},[110,709,710],{"class":142},"\"~/.claude/hooks/meu-script.sh\"\n",[110,712,713],{"class":112,"line":187},[110,714,715],{"class":116},"          }\n",[110,717,718],{"class":112,"line":193},[110,719,720],{"class":116},"        ]\n",[110,722,723],{"class":112,"line":201},[110,724,725],{"class":116},"      }\n",[110,727,728],{"class":112,"line":209},[110,729,234],{"class":116},[110,731,732],{"class":112,"line":217},[110,733,240],{"class":116},[110,735,736],{"class":112,"line":225},[110,737,246],{"class":116},[10,739,740,741,744,745,748],{},"O script recebe o input da ferramenta via ",[47,742,743],{},"stdin como JSON",". Pra bloquear uma ação, o script retorna um JSON com ",[25,746,747],{},"permissionDecision: \"deny\"",". Pra permitir, basta retornar exit code 0.",[750,751,753],"h3",{"id":752},"script-detectando-secrets-no-conteúdo","Script: detectando secrets no conteúdo",[101,755,759],{"className":756,"code":757,"language":758,"meta":106,"style":106},"language-bash shiki shiki-themes github-light github-dark","#!/bin/bash\n# ~/.claude/hooks/block-secrets.sh\n# Ignora arquivos markdown (podem conter exemplos de patterns)\nFILE_PATH=$(jq -r '.tool_input.file_path // .tool_input.filePath // \"\"' 2>/dev/null)\n\nif echo \"$FILE_PATH\" | grep -qiE '\\.(md|mdx|txt|rst)$'; then\n  exit 0\nfi\n\nCONTENT=$(jq -r '.tool_input | to_entries | map(.value) | join(\" \")' 2>/dev/null)\n\nif echo \"$CONTENT\" | grep -qiE 'AKIA[0-9A-Z]{16}|sk-[a-zA-Z0-9]{20,}|ghp_[a-zA-Z0-9]{36}|mongodb\\+srv://|BEGIN.*PRIVATE KEY|xox[bpas]-'; then\n  jq -n '{\n    hookSpecificOutput: {\n      hookEventName: \"PreToolUse\",\n      permissionDecision: \"deny\",\n      permissionDecisionReason: \"Secret detectado no conteudo\"\n    }\n  }'\nelse\n  exit 0\nfi\n","bash",[25,760,761,767,772,777,808,814,849,857,862,866,888,892,918,929,934,939,944,949,954,960,966,973],{"__ignoreMap":106},[110,762,763],{"class":112,"line":113},[110,764,766],{"class":765},"sJ8bj","#!/bin/bash\n",[110,768,769],{"class":112,"line":120},[110,770,771],{"class":765},"# ~/.claude/hooks/block-secrets.sh\n",[110,773,774],{"class":112,"line":130},[110,775,776],{"class":765},"# Ignora arquivos markdown (podem conter exemplos de patterns)\n",[110,778,779,782,786,789,793,796,799,802,805],{"class":112,"line":139},[110,780,781],{"class":116},"FILE_PATH",[110,783,785],{"class":784},"szBVR","=",[110,787,788],{"class":116},"$(",[110,790,792],{"class":791},"sScJk","jq",[110,794,795],{"class":123}," -r",[110,797,798],{"class":142}," '.tool_input.file_path // .tool_input.filePath // \"\"'",[110,800,801],{"class":784}," 2>",[110,803,804],{"class":142},"/dev/null",[110,806,807],{"class":116},")\n",[110,809,810],{"class":112,"line":149},[110,811,813],{"emptyLinePlaceholder":812},true,"\n",[110,815,816,819,822,825,828,831,834,837,840,843,846],{"class":112,"line":157},[110,817,818],{"class":784},"if",[110,820,821],{"class":123}," echo",[110,823,824],{"class":142}," \"",[110,826,827],{"class":116},"$FILE_PATH",[110,829,830],{"class":142},"\"",[110,832,833],{"class":784}," |",[110,835,836],{"class":791}," grep",[110,838,839],{"class":123}," -qiE",[110,841,842],{"class":142}," '\\.(md|mdx|txt|rst)$'",[110,844,845],{"class":116},"; ",[110,847,848],{"class":784},"then\n",[110,850,851,854],{"class":112,"line":165},[110,852,853],{"class":123},"  exit",[110,855,856],{"class":123}," 0\n",[110,858,859],{"class":112,"line":173},[110,860,861],{"class":784},"fi\n",[110,863,864],{"class":112,"line":181},[110,865,813],{"emptyLinePlaceholder":812},[110,867,868,871,873,875,877,879,882,884,886],{"class":112,"line":187},[110,869,870],{"class":116},"CONTENT",[110,872,785],{"class":784},[110,874,788],{"class":116},[110,876,792],{"class":791},[110,878,795],{"class":123},[110,880,881],{"class":142}," '.tool_input | to_entries | map(.value) | join(\" \")'",[110,883,801],{"class":784},[110,885,804],{"class":142},[110,887,807],{"class":116},[110,889,890],{"class":112,"line":193},[110,891,813],{"emptyLinePlaceholder":812},[110,893,894,896,898,900,903,905,907,909,911,914,916],{"class":112,"line":201},[110,895,818],{"class":784},[110,897,821],{"class":123},[110,899,824],{"class":142},[110,901,902],{"class":116},"$CONTENT",[110,904,830],{"class":142},[110,906,833],{"class":784},[110,908,836],{"class":791},[110,910,839],{"class":123},[110,912,913],{"class":142}," 'AKIA[0-9A-Z]{16}|sk-[a-zA-Z0-9]{20,}|ghp_[a-zA-Z0-9]{36}|mongodb\\+srv://|BEGIN.*PRIVATE KEY|xox[bpas]-'",[110,915,845],{"class":116},[110,917,848],{"class":784},[110,919,920,923,926],{"class":112,"line":209},[110,921,922],{"class":791},"  jq",[110,924,925],{"class":123}," -n",[110,927,928],{"class":142}," '{\n",[110,930,931],{"class":112,"line":217},[110,932,933],{"class":142},"    hookSpecificOutput: {\n",[110,935,936],{"class":112,"line":225},[110,937,938],{"class":142},"      hookEventName: \"PreToolUse\",\n",[110,940,941],{"class":112,"line":231},[110,942,943],{"class":142},"      permissionDecision: \"deny\",\n",[110,945,946],{"class":112,"line":237},[110,947,948],{"class":142},"      permissionDecisionReason: \"Secret detectado no conteudo\"\n",[110,950,951],{"class":112,"line":243},[110,952,953],{"class":142},"    }\n",[110,955,957],{"class":112,"line":956},19,[110,958,959],{"class":142},"  }'\n",[110,961,963],{"class":112,"line":962},20,[110,964,965],{"class":784},"else\n",[110,967,969,971],{"class":112,"line":968},21,[110,970,853],{"class":123},[110,972,856],{"class":123},[110,974,976],{"class":112,"line":975},22,[110,977,861],{"class":784},[10,979,980],{},"Esse hook roda antes de qualquer Write, Edit ou MultiEdit. Verifica se o conteúdo contém patterns de AWS Access Keys, OpenAI/Stripe keys, GitHub tokens, connection strings MongoDB, chaves privadas e Slack tokens. Se detectar, bloqueia a escrita.",[10,982,983,984,95,987,990],{},"Detalhe importante: o script ignora arquivos ",[25,985,986],{},".md",[25,988,989],{},".mdx",". Sem isso, um blog post que mencione esses patterns como exemplo (como este que estou escrevendo agora) seria bloqueado. Na prática, isso aconteceu comigo ao escrever este artigo. O hook bloqueou a escrita do próprio post porque o conteúdo continha os patterns de exemplo. A solução foi adicionar o filtro por extensão no topo do script.",[750,992,994],{"id":993},"script-protegendo-env-via-writeedit","Script: protegendo .env via Write/Edit",[101,996,998],{"className":756,"code":997,"language":758,"meta":106,"style":106},"#!/bin/bash\n# ~/.claude/hooks/block-env-write.sh\nFILE_PATH=$(jq -r '.tool_input.file_path // .tool_input.filePath // \"\"' 2>/dev/null)\n\nif echo \"$FILE_PATH\" | grep -qE '\\.env($|\\.)'; then\n  jq -n '{\n    hookSpecificOutput: {\n      hookEventName: \"PreToolUse\",\n      permissionDecision: \"deny\",\n      permissionDecisionReason: \"Escrita em arquivo .env bloqueada por hook\"\n    }\n  }'\nelse\n  exit 0\nfi\n",[25,999,1000,1004,1009,1029,1033,1059,1067,1071,1075,1079,1084,1088,1092,1096,1102],{"__ignoreMap":106},[110,1001,1002],{"class":112,"line":113},[110,1003,766],{"class":765},[110,1005,1006],{"class":112,"line":120},[110,1007,1008],{"class":765},"# ~/.claude/hooks/block-env-write.sh\n",[110,1010,1011,1013,1015,1017,1019,1021,1023,1025,1027],{"class":112,"line":130},[110,1012,781],{"class":116},[110,1014,785],{"class":784},[110,1016,788],{"class":116},[110,1018,792],{"class":791},[110,1020,795],{"class":123},[110,1022,798],{"class":142},[110,1024,801],{"class":784},[110,1026,804],{"class":142},[110,1028,807],{"class":116},[110,1030,1031],{"class":112,"line":139},[110,1032,813],{"emptyLinePlaceholder":812},[110,1034,1035,1037,1039,1041,1043,1045,1047,1049,1052,1055,1057],{"class":112,"line":149},[110,1036,818],{"class":784},[110,1038,821],{"class":123},[110,1040,824],{"class":142},[110,1042,827],{"class":116},[110,1044,830],{"class":142},[110,1046,833],{"class":784},[110,1048,836],{"class":791},[110,1050,1051],{"class":123}," -qE",[110,1053,1054],{"class":142}," '\\.env($|\\.)'",[110,1056,845],{"class":116},[110,1058,848],{"class":784},[110,1060,1061,1063,1065],{"class":112,"line":157},[110,1062,922],{"class":791},[110,1064,925],{"class":123},[110,1066,928],{"class":142},[110,1068,1069],{"class":112,"line":165},[110,1070,933],{"class":142},[110,1072,1073],{"class":112,"line":173},[110,1074,938],{"class":142},[110,1076,1077],{"class":112,"line":181},[110,1078,943],{"class":142},[110,1080,1081],{"class":112,"line":187},[110,1082,1083],{"class":142},"      permissionDecisionReason: \"Escrita em arquivo .env bloqueada por hook\"\n",[110,1085,1086],{"class":112,"line":193},[110,1087,953],{"class":142},[110,1089,1090],{"class":112,"line":201},[110,1091,959],{"class":142},[110,1093,1094],{"class":112,"line":209},[110,1095,965],{"class":784},[110,1097,1098,1100],{"class":112,"line":217},[110,1099,853],{"class":123},[110,1101,856],{"class":123},[110,1103,1104],{"class":112,"line":225},[110,1105,861],{"class":784},[750,1107,1109],{"id":1108},"script-protegendo-env-via-bash","Script: protegendo .env via Bash",[10,1111,1112,1113,95,1115,1118,1119,1122,1123,1126],{},"O deny bloqueia ",[25,1114,262],{},[25,1116,1117],{},"Write(./.env)",", mas o Claude Code pode tentar ",[25,1120,1121],{},"cat .env"," ou ",[25,1124,1125],{},"echo \"KEY=value\" >> .env"," pelo Bash. O hook pega esses caminhos indiretos:",[101,1128,1130],{"className":756,"code":1129,"language":758,"meta":106,"style":106},"#!/bin/bash\n# ~/.claude/hooks/block-env-bash.sh\nCOMMAND=$(jq -r '.tool_input.command' 2>/dev/null)\n\nif echo \"$COMMAND\" | grep -qiE '>\\s*\\.env|>>\\s*\\.env|cat\\s+\\.env|head\\s+\\.env|tail\\s+\\.env|source\\s+\\.env|cp\\s.*\\.env|mv\\s.*\\.env|printenv'; then\n  jq -n '{\n    hookSpecificOutput: {\n      hookEventName: \"PreToolUse\",\n      permissionDecision: \"deny\",\n      permissionDecisionReason: \"Comando manipula ou expoe arquivo .env\"\n    }\n  }'\nelse\n  exit 0\nfi\n",[25,1131,1132,1136,1141,1163,1167,1193,1201,1205,1209,1213,1218,1222,1226,1230,1236],{"__ignoreMap":106},[110,1133,1134],{"class":112,"line":113},[110,1135,766],{"class":765},[110,1137,1138],{"class":112,"line":120},[110,1139,1140],{"class":765},"# ~/.claude/hooks/block-env-bash.sh\n",[110,1142,1143,1146,1148,1150,1152,1154,1157,1159,1161],{"class":112,"line":130},[110,1144,1145],{"class":116},"COMMAND",[110,1147,785],{"class":784},[110,1149,788],{"class":116},[110,1151,792],{"class":791},[110,1153,795],{"class":123},[110,1155,1156],{"class":142}," '.tool_input.command'",[110,1158,801],{"class":784},[110,1160,804],{"class":142},[110,1162,807],{"class":116},[110,1164,1165],{"class":112,"line":139},[110,1166,813],{"emptyLinePlaceholder":812},[110,1168,1169,1171,1173,1175,1178,1180,1182,1184,1186,1189,1191],{"class":112,"line":149},[110,1170,818],{"class":784},[110,1172,821],{"class":123},[110,1174,824],{"class":142},[110,1176,1177],{"class":116},"$COMMAND",[110,1179,830],{"class":142},[110,1181,833],{"class":784},[110,1183,836],{"class":791},[110,1185,839],{"class":123},[110,1187,1188],{"class":142}," '>\\s*\\.env|>>\\s*\\.env|cat\\s+\\.env|head\\s+\\.env|tail\\s+\\.env|source\\s+\\.env|cp\\s.*\\.env|mv\\s.*\\.env|printenv'",[110,1190,845],{"class":116},[110,1192,848],{"class":784},[110,1194,1195,1197,1199],{"class":112,"line":157},[110,1196,922],{"class":791},[110,1198,925],{"class":123},[110,1200,928],{"class":142},[110,1202,1203],{"class":112,"line":165},[110,1204,933],{"class":142},[110,1206,1207],{"class":112,"line":173},[110,1208,938],{"class":142},[110,1210,1211],{"class":112,"line":181},[110,1212,943],{"class":142},[110,1214,1215],{"class":112,"line":187},[110,1216,1217],{"class":142},"      permissionDecisionReason: \"Comando manipula ou expoe arquivo .env\"\n",[110,1219,1220],{"class":112,"line":193},[110,1221,953],{"class":142},[110,1223,1224],{"class":112,"line":201},[110,1225,959],{"class":142},[110,1227,1228],{"class":112,"line":209},[110,1229,965],{"class":784},[110,1231,1232,1234],{"class":112,"line":217},[110,1233,853],{"class":123},[110,1235,856],{"class":123},[110,1237,1238],{"class":112,"line":225},[110,1239,861],{"class":784},[750,1241,1243],{"id":1242},"script-audit-log","Script: audit log",[10,1245,1246,1247,1250],{},"Um hook ",[25,1248,1249],{},"PostToolUse"," que loga todos os comandos Bash executados. Não bloqueia nada, só registra:",[101,1252,1254],{"className":756,"code":1253,"language":758,"meta":106,"style":106},"#!/bin/bash\n# ~/.claude/hooks/audit-log.sh\nCOMMAND=$(jq -r '.tool_input.command // \"unknown\"' 2>/dev/null)\necho \"$(date -u +%Y-%m-%dT%H:%M:%SZ) | Bash | $(echo \"$COMMAND\" | head -c 200)\" >> ~/.claude/audit.log\nexit 0\n",[25,1255,1256,1260,1265,1286,1333],{"__ignoreMap":106},[110,1257,1258],{"class":112,"line":113},[110,1259,766],{"class":765},[110,1261,1262],{"class":112,"line":120},[110,1263,1264],{"class":765},"# ~/.claude/hooks/audit-log.sh\n",[110,1266,1267,1269,1271,1273,1275,1277,1280,1282,1284],{"class":112,"line":130},[110,1268,1145],{"class":116},[110,1270,785],{"class":784},[110,1272,788],{"class":116},[110,1274,792],{"class":791},[110,1276,795],{"class":123},[110,1278,1279],{"class":142}," '.tool_input.command // \"unknown\"'",[110,1281,801],{"class":784},[110,1283,804],{"class":142},[110,1285,807],{"class":116},[110,1287,1288,1291,1294,1297,1300,1303,1305,1307,1309,1312,1315,1318,1321,1324,1327,1330],{"class":112,"line":139},[110,1289,1290],{"class":123},"echo",[110,1292,1293],{"class":142}," \"$(",[110,1295,1296],{"class":791},"date",[110,1298,1299],{"class":123}," -u",[110,1301,1302],{"class":142}," +%Y-%m-%dT%H:%M:%SZ) | Bash | $(",[110,1304,1290],{"class":123},[110,1306,824],{"class":142},[110,1308,1177],{"class":116},[110,1310,1311],{"class":142},"\" ",[110,1313,1314],{"class":784},"|",[110,1316,1317],{"class":791}," head",[110,1319,1320],{"class":123}," -c",[110,1322,1323],{"class":123}," 200",[110,1325,1326],{"class":142},")\"",[110,1328,1329],{"class":784}," >>",[110,1331,1332],{"class":142}," ~/.claude/audit.log\n",[110,1334,1335,1338],{"class":112,"line":149},[110,1336,1337],{"class":123},"exit",[110,1339,856],{"class":123},[750,1341,1343],{"id":1342},"a-configuração-dos-hooks-no-settingsjson","A configuração dos hooks no settings.json",[101,1345,1347],{"className":103,"code":1346,"language":105,"meta":106,"style":106},"{\n  \"hooks\": {\n    \"PreToolUse\": [\n      {\n        \"matcher\": \"Write|Edit|MultiEdit\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.claude/hooks/block-secrets.sh\"\n          }\n        ]\n      },\n      {\n        \"matcher\": \"Write|Edit|MultiEdit\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.claude/hooks/block-env-write.sh\"\n          }\n        ]\n      },\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.claude/hooks/block-env-bash.sh\"\n          }\n        ]\n      }\n    ],\n    \"PostToolUse\": [\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.claude/hooks/audit-log.sh\"\n          }\n        ]\n      }\n    ]\n  }\n}\n",[25,1348,1349,1353,1359,1365,1369,1380,1386,1390,1400,1409,1413,1417,1422,1426,1436,1442,1446,1456,1465,1469,1473,1477,1481,1492,1499,1504,1515,1525,1530,1535,1540,1545,1553,1558,1569,1576,1581,1592,1602,1607,1612,1617,1622,1627],{"__ignoreMap":106},[110,1350,1351],{"class":112,"line":113},[110,1352,117],{"class":116},[110,1354,1355,1357],{"class":112,"line":120},[110,1356,649],{"class":123},[110,1358,127],{"class":116},[110,1360,1361,1363],{"class":112,"line":130},[110,1362,656],{"class":123},[110,1364,136],{"class":116},[110,1366,1367],{"class":112,"line":139},[110,1368,663],{"class":116},[110,1370,1371,1373,1375,1378],{"class":112,"line":149},[110,1372,668],{"class":123},[110,1374,671],{"class":116},[110,1376,1377],{"class":142},"\"Write|Edit|MultiEdit\"",[110,1379,146],{"class":116},[110,1381,1382,1384],{"class":112,"line":157},[110,1383,681],{"class":123},[110,1385,136],{"class":116},[110,1387,1388],{"class":112,"line":165},[110,1389,688],{"class":116},[110,1391,1392,1394,1396,1398],{"class":112,"line":173},[110,1393,693],{"class":123},[110,1395,671],{"class":116},[110,1397,698],{"class":142},[110,1399,146],{"class":116},[110,1401,1402,1404,1406],{"class":112,"line":181},[110,1403,705],{"class":123},[110,1405,671],{"class":116},[110,1407,1408],{"class":142},"\"~/.claude/hooks/block-secrets.sh\"\n",[110,1410,1411],{"class":112,"line":187},[110,1412,715],{"class":116},[110,1414,1415],{"class":112,"line":193},[110,1416,720],{"class":116},[110,1418,1419],{"class":112,"line":201},[110,1420,1421],{"class":116},"      },\n",[110,1423,1424],{"class":112,"line":209},[110,1425,663],{"class":116},[110,1427,1428,1430,1432,1434],{"class":112,"line":217},[110,1429,668],{"class":123},[110,1431,671],{"class":116},[110,1433,1377],{"class":142},[110,1435,146],{"class":116},[110,1437,1438,1440],{"class":112,"line":225},[110,1439,681],{"class":123},[110,1441,136],{"class":116},[110,1443,1444],{"class":112,"line":231},[110,1445,688],{"class":116},[110,1447,1448,1450,1452,1454],{"class":112,"line":237},[110,1449,693],{"class":123},[110,1451,671],{"class":116},[110,1453,698],{"class":142},[110,1455,146],{"class":116},[110,1457,1458,1460,1462],{"class":112,"line":243},[110,1459,705],{"class":123},[110,1461,671],{"class":116},[110,1463,1464],{"class":142},"\"~/.claude/hooks/block-env-write.sh\"\n",[110,1466,1467],{"class":112,"line":956},[110,1468,715],{"class":116},[110,1470,1471],{"class":112,"line":962},[110,1472,720],{"class":116},[110,1474,1475],{"class":112,"line":968},[110,1476,1421],{"class":116},[110,1478,1479],{"class":112,"line":975},[110,1480,663],{"class":116},[110,1482,1484,1486,1488,1490],{"class":112,"line":1483},23,[110,1485,668],{"class":123},[110,1487,671],{"class":116},[110,1489,674],{"class":142},[110,1491,146],{"class":116},[110,1493,1495,1497],{"class":112,"line":1494},24,[110,1496,681],{"class":123},[110,1498,136],{"class":116},[110,1500,1502],{"class":112,"line":1501},25,[110,1503,688],{"class":116},[110,1505,1507,1509,1511,1513],{"class":112,"line":1506},26,[110,1508,693],{"class":123},[110,1510,671],{"class":116},[110,1512,698],{"class":142},[110,1514,146],{"class":116},[110,1516,1518,1520,1522],{"class":112,"line":1517},27,[110,1519,705],{"class":123},[110,1521,671],{"class":116},[110,1523,1524],{"class":142},"\"~/.claude/hooks/block-env-bash.sh\"\n",[110,1526,1528],{"class":112,"line":1527},28,[110,1529,715],{"class":116},[110,1531,1533],{"class":112,"line":1532},29,[110,1534,720],{"class":116},[110,1536,1538],{"class":112,"line":1537},30,[110,1539,725],{"class":116},[110,1541,1543],{"class":112,"line":1542},31,[110,1544,190],{"class":116},[110,1546,1548,1551],{"class":112,"line":1547},32,[110,1549,1550],{"class":123},"    \"PostToolUse\"",[110,1552,136],{"class":116},[110,1554,1556],{"class":112,"line":1555},33,[110,1557,663],{"class":116},[110,1559,1561,1563,1565,1567],{"class":112,"line":1560},34,[110,1562,668],{"class":123},[110,1564,671],{"class":116},[110,1566,674],{"class":142},[110,1568,146],{"class":116},[110,1570,1572,1574],{"class":112,"line":1571},35,[110,1573,681],{"class":123},[110,1575,136],{"class":116},[110,1577,1579],{"class":112,"line":1578},36,[110,1580,688],{"class":116},[110,1582,1584,1586,1588,1590],{"class":112,"line":1583},37,[110,1585,693],{"class":123},[110,1587,671],{"class":116},[110,1589,698],{"class":142},[110,1591,146],{"class":116},[110,1593,1595,1597,1599],{"class":112,"line":1594},38,[110,1596,705],{"class":123},[110,1598,671],{"class":116},[110,1600,1601],{"class":142},"\"~/.claude/hooks/audit-log.sh\"\n",[110,1603,1605],{"class":112,"line":1604},39,[110,1606,715],{"class":116},[110,1608,1610],{"class":112,"line":1609},40,[110,1611,720],{"class":116},[110,1613,1615],{"class":112,"line":1614},41,[110,1616,725],{"class":116},[110,1618,1620],{"class":112,"line":1619},42,[110,1621,234],{"class":116},[110,1623,1625],{"class":112,"line":1624},43,[110,1626,240],{"class":116},[110,1628,1630],{"class":112,"line":1629},44,[110,1631,246],{"class":116},[10,1633,1634,1635,1637,1638,1641,1642,1644,1645,1647],{},"Cada matcher filtra a ferramenta. O array ",[25,1636,634],{}," contém os handlers com ",[25,1639,1640],{},"type: \"command\""," e o path do script. Os scripts leem JSON do stdin com ",[25,1643,792],{}," e retornam JSON com ",[25,1646,747],{}," pra bloquear ou exit code 0 pra permitir.",[37,1649,1651],{"id":1650},"a-configuração-completa-que-uso","A configuração completa que uso",[101,1653,1655],{"className":103,"code":1654,"language":105,"meta":106,"style":106},"{\n  \"permissions\": {\n    \"allow\": [\n      \"Bash(*)\",\n      \"Read(*)\",\n      \"Edit(*)\",\n      \"Write(*)\",\n      \"MultiEdit(*)\",\n      \"LS(**)\",\n      \"Glob(*)\",\n      \"Grep(*)\",\n      \"NotebookRead(*)\",\n      \"NotebookEdit(*)\",\n      \"TodoRead(*)\",\n      \"TodoWrite(*)\",\n      \"WebSearch(*)\",\n      \"WebFetch(*)\"\n    ],\n    \"deny\": [\n      \"Read(./.env)\",\n      \"Read(./.env.*)\",\n      \"Write(./.env)\",\n      \"Write(./.env.*)\",\n      \"Edit(./.env)\",\n      \"Edit(./.env.*)\",\n      \"Read(./secrets/**)\",\n      \"Write(./secrets/**)\",\n      \"Edit(./secrets/**)\",\n      \"Read(./config/credentials.json)\",\n      \"Write(./config/credentials.json)\",\n      \"Edit(./config/credentials.json)\",\n      \"Read(./**/*.pem)\",\n      \"Read(./**/*.key)\",\n      \"Read(./**/*serviceAccountKey*)\",\n      \"Read(./**/credentials*.json)\",\n      \"Bash(rm -rf *)\",\n      \"Bash(git push --force*)\",\n      \"Bash(git reset --hard*)\"\n    ]\n  },\n  \"hooks\": {\n    \"PreToolUse\": [\n      {\n        \"matcher\": \"Write|Edit|MultiEdit\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.claude/hooks/block-secrets.sh\"\n          }\n        ]\n      },\n      {\n        \"matcher\": \"Write|Edit|MultiEdit\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.claude/hooks/block-env-write.sh\"\n          }\n        ]\n      },\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.claude/hooks/block-env-bash.sh\"\n          }\n        ]\n      }\n    ],\n    \"PostToolUse\": [\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/.claude/hooks/audit-log.sh\"\n          }\n        ]\n      }\n    ]\n  }\n}\n",[25,1656,1657,1661,1667,1673,1679,1685,1691,1697,1704,1711,1717,1724,1731,1738,1745,1752,1759,1764,1768,1774,1780,1786,1793,1800,1807,1814,1820,1827,1834,1841,1848,1855,1862,1869,1876,1883,1890,1897,1902,1906,1911,1917,1923,1927,1937,1944,1949,1960,1969,1974,1979,1984,1989,2000,2007,2012,2023,2032,2037,2042,2047,2052,2063,2070,2075,2086,2095,2100,2105,2110,2115,2122,2127,2138,2145,2150,2161,2170,2175,2180,2185,2190,2195],{"__ignoreMap":106},[110,1658,1659],{"class":112,"line":113},[110,1660,117],{"class":116},[110,1662,1663,1665],{"class":112,"line":120},[110,1664,124],{"class":123},[110,1666,127],{"class":116},[110,1668,1669,1671],{"class":112,"line":130},[110,1670,133],{"class":123},[110,1672,136],{"class":116},[110,1674,1675,1677],{"class":112,"line":139},[110,1676,143],{"class":142},[110,1678,146],{"class":116},[110,1680,1681,1683],{"class":112,"line":149},[110,1682,152],{"class":142},[110,1684,146],{"class":116},[110,1686,1687,1689],{"class":112,"line":157},[110,1688,160],{"class":142},[110,1690,146],{"class":116},[110,1692,1693,1695],{"class":112,"line":165},[110,1694,168],{"class":142},[110,1696,146],{"class":116},[110,1698,1699,1702],{"class":112,"line":173},[110,1700,1701],{"class":142},"      \"MultiEdit(*)\"",[110,1703,146],{"class":116},[110,1705,1706,1709],{"class":112,"line":181},[110,1707,1708],{"class":142},"      \"LS(**)\"",[110,1710,146],{"class":116},[110,1712,1713,1715],{"class":112,"line":187},[110,1714,176],{"class":142},[110,1716,146],{"class":116},[110,1718,1719,1722],{"class":112,"line":193},[110,1720,1721],{"class":142},"      \"Grep(*)\"",[110,1723,146],{"class":116},[110,1725,1726,1729],{"class":112,"line":201},[110,1727,1728],{"class":142},"      \"NotebookRead(*)\"",[110,1730,146],{"class":116},[110,1732,1733,1736],{"class":112,"line":209},[110,1734,1735],{"class":142},"      \"NotebookEdit(*)\"",[110,1737,146],{"class":116},[110,1739,1740,1743],{"class":112,"line":217},[110,1741,1742],{"class":142},"      \"TodoRead(*)\"",[110,1744,146],{"class":116},[110,1746,1747,1750],{"class":112,"line":225},[110,1748,1749],{"class":142},"      \"TodoWrite(*)\"",[110,1751,146],{"class":116},[110,1753,1754,1757],{"class":112,"line":231},[110,1755,1756],{"class":142},"      \"WebSearch(*)\"",[110,1758,146],{"class":116},[110,1760,1761],{"class":112,"line":237},[110,1762,1763],{"class":142},"      \"WebFetch(*)\"\n",[110,1765,1766],{"class":112,"line":243},[110,1767,190],{"class":116},[110,1769,1770,1772],{"class":112,"line":956},[110,1771,196],{"class":123},[110,1773,136],{"class":116},[110,1775,1776,1778],{"class":112,"line":962},[110,1777,204],{"class":142},[110,1779,146],{"class":116},[110,1781,1782,1784],{"class":112,"line":968},[110,1783,212],{"class":142},[110,1785,146],{"class":116},[110,1787,1788,1791],{"class":112,"line":975},[110,1789,1790],{"class":142},"      \"Write(./.env)\"",[110,1792,146],{"class":116},[110,1794,1795,1798],{"class":112,"line":1483},[110,1796,1797],{"class":142},"      \"Write(./.env.*)\"",[110,1799,146],{"class":116},[110,1801,1802,1805],{"class":112,"line":1494},[110,1803,1804],{"class":142},"      \"Edit(./.env)\"",[110,1806,146],{"class":116},[110,1808,1809,1812],{"class":112,"line":1501},[110,1810,1811],{"class":142},"      \"Edit(./.env.*)\"",[110,1813,146],{"class":116},[110,1815,1816,1818],{"class":112,"line":1506},[110,1817,220],{"class":142},[110,1819,146],{"class":116},[110,1821,1822,1825],{"class":112,"line":1517},[110,1823,1824],{"class":142},"      \"Write(./secrets/**)\"",[110,1826,146],{"class":116},[110,1828,1829,1832],{"class":112,"line":1527},[110,1830,1831],{"class":142},"      \"Edit(./secrets/**)\"",[110,1833,146],{"class":116},[110,1835,1836,1839],{"class":112,"line":1532},[110,1837,1838],{"class":142},"      \"Read(./config/credentials.json)\"",[110,1840,146],{"class":116},[110,1842,1843,1846],{"class":112,"line":1537},[110,1844,1845],{"class":142},"      \"Write(./config/credentials.json)\"",[110,1847,146],{"class":116},[110,1849,1850,1853],{"class":112,"line":1542},[110,1851,1852],{"class":142},"      \"Edit(./config/credentials.json)\"",[110,1854,146],{"class":116},[110,1856,1857,1860],{"class":112,"line":1547},[110,1858,1859],{"class":142},"      \"Read(./**/*.pem)\"",[110,1861,146],{"class":116},[110,1863,1864,1867],{"class":112,"line":1555},[110,1865,1866],{"class":142},"      \"Read(./**/*.key)\"",[110,1868,146],{"class":116},[110,1870,1871,1874],{"class":112,"line":1560},[110,1872,1873],{"class":142},"      \"Read(./**/*serviceAccountKey*)\"",[110,1875,146],{"class":116},[110,1877,1878,1881],{"class":112,"line":1571},[110,1879,1880],{"class":142},"      \"Read(./**/credentials*.json)\"",[110,1882,146],{"class":116},[110,1884,1885,1888],{"class":112,"line":1578},[110,1886,1887],{"class":142},"      \"Bash(rm -rf *)\"",[110,1889,146],{"class":116},[110,1891,1892,1895],{"class":112,"line":1583},[110,1893,1894],{"class":142},"      \"Bash(git push --force*)\"",[110,1896,146],{"class":116},[110,1898,1899],{"class":112,"line":1594},[110,1900,1901],{"class":142},"      \"Bash(git reset --hard*)\"\n",[110,1903,1904],{"class":112,"line":1604},[110,1905,234],{"class":116},[110,1907,1908],{"class":112,"line":1609},[110,1909,1910],{"class":116},"  },\n",[110,1912,1913,1915],{"class":112,"line":1614},[110,1914,649],{"class":123},[110,1916,127],{"class":116},[110,1918,1919,1921],{"class":112,"line":1619},[110,1920,656],{"class":123},[110,1922,136],{"class":116},[110,1924,1925],{"class":112,"line":1624},[110,1926,663],{"class":116},[110,1928,1929,1931,1933,1935],{"class":112,"line":1629},[110,1930,668],{"class":123},[110,1932,671],{"class":116},[110,1934,1377],{"class":142},[110,1936,146],{"class":116},[110,1938,1940,1942],{"class":112,"line":1939},45,[110,1941,681],{"class":123},[110,1943,136],{"class":116},[110,1945,1947],{"class":112,"line":1946},46,[110,1948,688],{"class":116},[110,1950,1952,1954,1956,1958],{"class":112,"line":1951},47,[110,1953,693],{"class":123},[110,1955,671],{"class":116},[110,1957,698],{"class":142},[110,1959,146],{"class":116},[110,1961,1963,1965,1967],{"class":112,"line":1962},48,[110,1964,705],{"class":123},[110,1966,671],{"class":116},[110,1968,1408],{"class":142},[110,1970,1972],{"class":112,"line":1971},49,[110,1973,715],{"class":116},[110,1975,1977],{"class":112,"line":1976},50,[110,1978,720],{"class":116},[110,1980,1982],{"class":112,"line":1981},51,[110,1983,1421],{"class":116},[110,1985,1987],{"class":112,"line":1986},52,[110,1988,663],{"class":116},[110,1990,1992,1994,1996,1998],{"class":112,"line":1991},53,[110,1993,668],{"class":123},[110,1995,671],{"class":116},[110,1997,1377],{"class":142},[110,1999,146],{"class":116},[110,2001,2003,2005],{"class":112,"line":2002},54,[110,2004,681],{"class":123},[110,2006,136],{"class":116},[110,2008,2010],{"class":112,"line":2009},55,[110,2011,688],{"class":116},[110,2013,2015,2017,2019,2021],{"class":112,"line":2014},56,[110,2016,693],{"class":123},[110,2018,671],{"class":116},[110,2020,698],{"class":142},[110,2022,146],{"class":116},[110,2024,2026,2028,2030],{"class":112,"line":2025},57,[110,2027,705],{"class":123},[110,2029,671],{"class":116},[110,2031,1464],{"class":142},[110,2033,2035],{"class":112,"line":2034},58,[110,2036,715],{"class":116},[110,2038,2040],{"class":112,"line":2039},59,[110,2041,720],{"class":116},[110,2043,2045],{"class":112,"line":2044},60,[110,2046,1421],{"class":116},[110,2048,2050],{"class":112,"line":2049},61,[110,2051,663],{"class":116},[110,2053,2055,2057,2059,2061],{"class":112,"line":2054},62,[110,2056,668],{"class":123},[110,2058,671],{"class":116},[110,2060,674],{"class":142},[110,2062,146],{"class":116},[110,2064,2066,2068],{"class":112,"line":2065},63,[110,2067,681],{"class":123},[110,2069,136],{"class":116},[110,2071,2073],{"class":112,"line":2072},64,[110,2074,688],{"class":116},[110,2076,2078,2080,2082,2084],{"class":112,"line":2077},65,[110,2079,693],{"class":123},[110,2081,671],{"class":116},[110,2083,698],{"class":142},[110,2085,146],{"class":116},[110,2087,2089,2091,2093],{"class":112,"line":2088},66,[110,2090,705],{"class":123},[110,2092,671],{"class":116},[110,2094,1524],{"class":142},[110,2096,2098],{"class":112,"line":2097},67,[110,2099,715],{"class":116},[110,2101,2103],{"class":112,"line":2102},68,[110,2104,720],{"class":116},[110,2106,2108],{"class":112,"line":2107},69,[110,2109,725],{"class":116},[110,2111,2113],{"class":112,"line":2112},70,[110,2114,190],{"class":116},[110,2116,2118,2120],{"class":112,"line":2117},71,[110,2119,1550],{"class":123},[110,2121,136],{"class":116},[110,2123,2125],{"class":112,"line":2124},72,[110,2126,663],{"class":116},[110,2128,2130,2132,2134,2136],{"class":112,"line":2129},73,[110,2131,668],{"class":123},[110,2133,671],{"class":116},[110,2135,674],{"class":142},[110,2137,146],{"class":116},[110,2139,2141,2143],{"class":112,"line":2140},74,[110,2142,681],{"class":123},[110,2144,136],{"class":116},[110,2146,2148],{"class":112,"line":2147},75,[110,2149,688],{"class":116},[110,2151,2153,2155,2157,2159],{"class":112,"line":2152},76,[110,2154,693],{"class":123},[110,2156,671],{"class":116},[110,2158,698],{"class":142},[110,2160,146],{"class":116},[110,2162,2164,2166,2168],{"class":112,"line":2163},77,[110,2165,705],{"class":123},[110,2167,671],{"class":116},[110,2169,1601],{"class":142},[110,2171,2173],{"class":112,"line":2172},78,[110,2174,715],{"class":116},[110,2176,2178],{"class":112,"line":2177},79,[110,2179,720],{"class":116},[110,2181,2183],{"class":112,"line":2182},80,[110,2184,725],{"class":116},[110,2186,2188],{"class":112,"line":2187},81,[110,2189,234],{"class":116},[110,2191,2193],{"class":112,"line":2192},82,[110,2194,240],{"class":116},[110,2196,2198],{"class":112,"line":2197},83,[110,2199,246],{"class":116},[10,2201,2202,2203,353,2205,353,2207,2210,2211,2214],{},"Sim, o allow é amplo. ",[25,2204,479],{},[25,2206,258],{},[25,2208,2209],{},"Write(*)",". Tudo liberado. Trabalho sozinho nos meus projetos, conheço o que cada comando faz, e travar o Claude Code pra pedir confirmação a cada ",[25,2212,2213],{},"ls"," destrói a produtividade.",[10,2216,2217,2218,2220,2221,2223],{},"Mas permissão ampla não significa sem proteção. O deny list bloqueia os arquivos sensíveis (",[25,2219,27],{},", secrets, credenciais, chaves privadas). Os hooks validam o conteúdo antes de qualquer escrita e bloqueiam comandos que manipulam ",[25,2222,27],{}," pelo shell. O audit log registra tudo que foi executado.",[10,2225,2226,2227,2229,2230,2232],{},"A diferença entre ser permissivo por descuido e ser permissivo de forma controlada é ter as camadas de proteção configuradas. O ",[25,2228,479],{}," sem deny rules e sem hooks é um risco. O ",[25,2231,479],{}," com deny list, hooks de validação e audit log é uma decisão consciente de quem entende os vetores de ataque e escolheu onde colocar as barreiras.",[37,2234,2236],{"id":2235},"claudemd-a-terceira-camada","CLAUDE.md: a terceira camada",[10,2238,249,2239,2241,2242,2244],{},[25,2240,72],{}," na raiz do projeto complementa o ",[25,2243,626],{}," com regras em linguagem natural. O JSON define permissões binárias (pode/não pode). O markdown define comportamento (como agir).",[101,2246,2250],{"className":2247,"code":2248,"language":2249,"meta":106,"style":106},"language-markdown shiki shiki-themes github-light github-dark","## Segurança\n\n- Nunca incluir secrets, tokens ou chaves em código ou documentação\n- Nunca fazer commit de arquivos .env\n- Usar variáveis de ambiente (process.env) para toda configuração sensível\n- Nunca logar dados sensíveis (senhas, tokens, PII)\n- Sanitizar todo input antes de usar em queries\n","markdown",[25,2251,2252,2257,2261,2266,2271,2276,2281],{"__ignoreMap":106},[110,2253,2254],{"class":112,"line":113},[110,2255,2256],{},"## Segurança\n",[110,2258,2259],{"class":112,"line":120},[110,2260,813],{"emptyLinePlaceholder":812},[110,2262,2263],{"class":112,"line":130},[110,2264,2265],{},"- Nunca incluir secrets, tokens ou chaves em código ou documentação\n",[110,2267,2268],{"class":112,"line":139},[110,2269,2270],{},"- Nunca fazer commit de arquivos .env\n",[110,2272,2273],{"class":112,"line":149},[110,2274,2275],{},"- Usar variáveis de ambiente (process.env) para toda configuração sensível\n",[110,2277,2278],{"class":112,"line":157},[110,2279,2280],{},"- Nunca logar dados sensíveis (senhas, tokens, PII)\n",[110,2282,2283],{"class":112,"line":165},[110,2284,2285],{},"- Sanitizar todo input antes de usar em queries\n",[10,2287,2288,2289,2292],{},"O Claude Code lê essas regras no início de cada sessão e as aplica em tudo que faz. Se for criar um teste que precisa de uma API key, vai usar ",[25,2290,2291],{},"process.env.API_KEY"," ou um mock em vez de um valor hardcoded.",[10,2294,249,2295,2297],{},[25,2296,72],{}," pega o que o JSON não consegue expressar. \"Nunca logar dados sensíveis\" não é uma permissão. É um comportamento. O Claude Code entende isso e aplica em todo código que escreve.",[37,2299,2301],{"id":2300},"o-que-acontece-se-não-configurar-nada","O que acontece se não configurar nada",[10,2303,2304],{},"Sem deny rules e sem hooks, o Claude Code pode:",[2306,2307,2308,2315,2318,2321,2324,2330],"ol",{},[2309,2310,2311,2312,2314],"li",{},"Ler o ",[25,2313,27],{}," quando tentar entender a configuração do projeto",[2309,2316,2317],{},"Incluir valores reais de variáveis de ambiente em exemplos de código",[2309,2319,2320],{},"Exibir connection strings no output ao explicar como o banco funciona",[2309,2322,2323],{},"Copiar secrets pra arquivos de teste ou documentação",[2309,2325,2326,2327,2329],{},"Sobrescrever o ",[25,2328,27],{}," com valores diferentes ao tentar \"ajudar\"",[2309,2331,2332,2333,2335],{},"Rodar ",[25,2334,1121],{}," pelo Bash, contornando deny rules de Read",[10,2337,2338],{},"Nenhum desses cenários é malicioso. O Claude Code não está tentando roubar secrets. Ele simplesmente não sabe que aquele arquivo não deveria ser lido a menos que exista uma regra dizendo isso.",[10,2340,2341],{},"A configuração padrão do Claude Code é conservadora. Ele pede confirmação pra quase tudo. Mas quando as permissões são liberadas pra aumentar a produtividade (o que é normal e recomendado), o deny list e os hooks se tornam a última linha de defesa.",[37,2343,2345],{"id":2344},"as-quatro-camadas","As quatro camadas",[10,2347,2348],{},"Resumindo, a proteção funciona em camadas:",[2306,2350,2351,2360,2374,2382],{},[2309,2352,2353,2356,2357,2359],{},[47,2354,2355],{},"Deny rules por path"," — bloqueia Read/Write/Edit em ",[25,2358,27],{},", secrets, credenciais, chaves privadas",[2309,2361,2362,2365,2366,353,2368,353,2371],{},[47,2363,2364],{},"Deny rules por comando"," — bloqueia ",[25,2367,31],{},[25,2369,2370],{},"git push --force",[25,2372,2373],{},"git reset --hard",[2309,2375,2376,2379,2380],{},[47,2377,2378],{},"Hooks PreToolUse"," — scripts que leem o input da ferramenta via stdin, detectam secrets no conteúdo e bloqueiam comandos Bash que manipulam ",[25,2381,27],{},[2309,2383,2384,2386],{},[47,2385,72],{}," — regras semânticas que guiam o comportamento do Claude Code em tudo que ele escreve",[10,2388,2389,2390,2392],{},"Cada camada cobre o que a anterior não pega. Deny rules não analisam conteúdo. Hooks não definem comportamento. O ",[25,2391,72],{}," não tem enforcement binário. Juntas, cobrem praticamente todos os vetores.",[10,2394,2395],{},"Segurança não é só auditar o código que o Claude Code analisa. É configurar o ambiente pra que ele nunca tenha acesso ao que não precisa. Princípio do menor privilégio. Vale pra humanos, vale pra agentes de IA.",[2397,2398,2399],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":106,"searchDepth":120,"depth":120,"links":2401},[2402,2403,2404,2405,2406,2407,2414,2415,2416,2417],{"id":39,"depth":120,"text":40},{"id":83,"depth":120,"text":84},{"id":269,"depth":120,"text":270},{"id":366,"depth":120,"text":367},{"id":470,"depth":120,"text":471},{"id":608,"depth":120,"text":609,"children":2408},[2409,2410,2411,2412,2413],{"id":752,"depth":130,"text":753},{"id":993,"depth":130,"text":994},{"id":1108,"depth":130,"text":1109},{"id":1242,"depth":130,"text":1243},{"id":1342,"depth":130,"text":1343},{"id":1650,"depth":120,"text":1651},{"id":2235,"depth":120,"text":2236},{"id":2300,"depth":120,"text":2301},{"id":2344,"depth":120,"text":2345},"2026-03-06","Permissions deny, hooks de validação, CLAUDE.md restritivo. Como configurar o Claude Code pra nunca ler seus .env, nunca expor secrets e nunca rodar comandos destrutivos sem aprovação.","md",{},"/blog/claude-code-seguranca-configuracoes-que-protegem-seu-codigo",{"title":5,"description":2419},"blog/claude-code-seguranca-configuracoes-que-protegem-seu-codigo",[2426,2427,2428,2429],"seguranca","claude-code","devtools","configuracao","E-h3KRR30mDyP4LivSd-uJjnWNbYEkabchWY6mInTzM",1772834006002]