<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Keit Ollé</title>
    <description>The latest articles on DEV Community by Keit Ollé (@k8adev).</description>
    <link>https://dev.to/k8adev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F783676%2Fc4448f1c-5683-420c-800e-18ac58644e41.png</url>
      <title>DEV Community: Keit Ollé</title>
      <link>https://dev.to/k8adev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/k8adev"/>
    <language>en</language>
    <item>
      <title>Como impedir que um plugin de IA roube seus dados</title>
      <dc:creator>Keit Ollé</dc:creator>
      <pubDate>Sat, 11 Jul 2026 00:13:34 +0000</pubDate>
      <link>https://dev.to/k8adev/como-impedir-que-um-plugin-de-ia-roube-seus-dados-37aa</link>
      <guid>https://dev.to/k8adev/como-impedir-que-um-plugin-de-ia-roube-seus-dados-37aa</guid>
      <description>&lt;p&gt;Vi um comentário essa semana que tem fundamento e deveria ser a preocupação de todos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdkpcbj4yx49uoxyjka2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdkpcbj4yx49uoxyjka2x.png" width="630" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"Depois que eu li sobre injeção de malware nesses repos de skill eu tenho um maior medo de baixar skill dos outros e lançarem um curl esquisito, tava inclusive criando um setup pra testar de forma segura [...]"&lt;/p&gt;

&lt;p&gt;Uma skill, um plugin, um MCP server de terceiro roda com as mesmas permissões que você. Se ele dispara um comando, o comando roda na sua máquina, com suas credenciais, seu &lt;code&gt;~/.ssh&lt;/code&gt;, seu &lt;code&gt;.env&lt;/code&gt;. Ninguém precisa te hackear, você baixou e mandou rodar.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Aqui vou usar o Claude Code nos exemplos, é o que uso no dia a dia, então os nomes de arquivo e de campo são dele. Mas o raciocínio vale pra qualquer harness de IA que roda comando na sua máquina, Codex, Cursor e os outros. A sintaxe muda, o princípio é o mesmo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A boa notícia é que dá pra blindar isso pelo &lt;code&gt;settings.json&lt;/code&gt;. A má notícia é que a receita que circula por aí está errada, ou pelo menos incompleta. Todo mundo fala em bloquear o &lt;code&gt;curl&lt;/code&gt; e para por aí. Vou te mostrar por que isso não te salva sozinho, e o que realmente protege.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que bloquear o &lt;code&gt;curl&lt;/code&gt; é peneira
&lt;/h2&gt;

&lt;p&gt;O instinto é óbvio. Adiciona uma &lt;a href="https://code.claude.com/docs/pt/permissions" rel="noopener noreferrer"&gt;regra de &lt;code&gt;deny&lt;/code&gt;&lt;/a&gt; pro &lt;code&gt;curl&lt;/code&gt; e pronto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Bash(curl:*)"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso funciona pra &lt;code&gt;curl https://infostealer.com&lt;/code&gt;. O problema é que a regra faz &lt;em&gt;prefix-matching&lt;/em&gt;, ela casa com o começo do comando. E existe um número absurdo de jeitos de mandar dados pra fora que não começam com a palavra &lt;code&gt;curl&lt;/code&gt;. &lt;code&gt;wget&lt;/code&gt;. &lt;code&gt;/usr/bin/curl&lt;/code&gt; com caminho absoluto. &lt;code&gt;nc&lt;/code&gt;. &lt;code&gt;python -c "import urllib.request; ..."&lt;/code&gt;. &lt;code&gt;node -e "fetch(...)"&lt;/code&gt;. Cada um desses fura sua regra.&lt;/p&gt;

&lt;p&gt;Você nunca vai enumerar todas as formas de vazar dado. É uma corrida que você perde. Uma blocklist de comando é uma peneira, e o atacante só precisa achar um furo. A lógica está invertida.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proteja o alvo, não a saída
&lt;/h2&gt;

&lt;p&gt;Em vez de tentar listar todo jeito de vazar, proteja o que você não quer que seja lido. Isso é uma lista curta e fechada, ao contrário da lista de comandos que é infinita.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(./.env)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(./.env.*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(~/.ssh/**)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(~/.aws/**)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(**/secrets/**)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora não importa se a skill tenta &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;wget&lt;/code&gt; ou qualquer outro comando pra mandar o &lt;code&gt;.env&lt;/code&gt; pra fora. Ela não consegue nem ler o arquivo. Você fechou a origem do dado, não a porta de saída.&lt;/p&gt;

&lt;p&gt;Os padrões de caminho seguem a mesma sintaxe do &lt;code&gt;.gitignore&lt;/code&gt;. &lt;code&gt;~/&lt;/code&gt; é o home, &lt;code&gt;./&lt;/code&gt; é a raiz do projeto onde o &lt;code&gt;settings.json&lt;/code&gt; mora, &lt;code&gt;//&lt;/code&gt; é a raiz do sistema, &lt;code&gt;**&lt;/code&gt; casa qualquer profundidade. No meu settings de usuário as regras são na forma &lt;code&gt;Read(//**/.env)&lt;/code&gt;, que pega o arquivo em qualquer canto da máquina, não só no projeto aberto. E vale saber que o &lt;code&gt;deny&lt;/code&gt; segue symlink. Se um link aponta pra um arquivo negado, o link também é negado. Não dá pra driblar com atalho.&lt;/p&gt;

&lt;p&gt;Um detalhe honesto aqui, porque faz diferença. A regra &lt;code&gt;Read()&lt;/code&gt; cobre a ferramenta de leitura de arquivo do Claude e também os comandos de leitura que o Claude Code reconhece no Bash, tipo &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;head&lt;/code&gt;, &lt;code&gt;tail&lt;/code&gt; e &lt;code&gt;sed&lt;/code&gt;. O que ela não cobre é subprocesso que abre o arquivo por conta própria. Um script Python ou Node que dá &lt;code&gt;open(".env")&lt;/code&gt; não passa por essa checagem, e essa via só o sandbox fecha de verdade, no nível do sistema operacional.&lt;/p&gt;

&lt;p&gt;Mesmo assim eu não dependo do que a ferramenta reconhece ou deixa de reconhecer. No meu settings de usuário tem mais de cinquenta regras de &lt;code&gt;deny&lt;/code&gt; explícitas, cada comando de leitura cruzado com cada alvo. Um recorte real da minha lista:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Bash(cat *.env:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Bash(head *.env:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Bash(grep *.pem:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Bash(less *credentials:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Bash(cat *id_rsa*:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Bash(env:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"Bash(printenv:*)"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;head&lt;/code&gt;, &lt;code&gt;tail&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;less&lt;/code&gt;, &lt;code&gt;more&lt;/code&gt; e &lt;code&gt;diff&lt;/code&gt;, cada um contra &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;.pem&lt;/code&gt;, &lt;code&gt;.key&lt;/code&gt;, credencial e chave ssh. Custa nada manter e é garantia explícita, escrita por mim, não inferida pela ferramenta. E os dois últimos fecham outra porta, &lt;code&gt;env&lt;/code&gt; e &lt;code&gt;printenv&lt;/code&gt; despejam as variáveis de ambiente, e tem segredo que mora ali, não em arquivo.&lt;/p&gt;

&lt;p&gt;Mas repara, tudo isso ainda é lista. O que não está em nenhuma lista, um leitor obscuro, um script que abre o arquivo direto, passa. É por isso que as camadas de baixo existem, o hook que olha o comando inteiro e o sandbox que fecha no sistema operacional.&lt;/p&gt;

&lt;h2&gt;
  
  
  A ordem importa, e o &lt;code&gt;deny&lt;/code&gt; sempre ganha
&lt;/h2&gt;

&lt;p&gt;As três listas de &lt;code&gt;permissions&lt;/code&gt; são avaliadas numa ordem fixa. Primeiro &lt;code&gt;deny&lt;/code&gt;, depois &lt;code&gt;ask&lt;/code&gt;, depois &lt;code&gt;allow&lt;/code&gt;. A primeira que casa decide. Ou seja, um &lt;code&gt;deny&lt;/code&gt; amplo vence um &lt;code&gt;allow&lt;/code&gt; específico, você não consegue liberar por acidente algo que negou antes.&lt;/p&gt;

&lt;p&gt;No meu settings isso aparece na prática. &lt;code&gt;Bash(cat:*)&lt;/code&gt; está no &lt;code&gt;allow&lt;/code&gt;, o agente usa &lt;code&gt;cat&lt;/code&gt; o dia inteiro sem me pedir nada. E &lt;code&gt;Bash(cat *.env:*)&lt;/code&gt; está no &lt;code&gt;deny&lt;/code&gt;. Resultado, &lt;code&gt;cat&lt;/code&gt; funciona em tudo, menos em cima de segredo. Liberei a ferramenta, não o alvo.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;ask&lt;/code&gt; é o meio-termo. Ele força uma aprovação toda vez, sem exceção. Se você quer permitir rede mas com você no loop, é o campo certo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ask"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Bash(curl:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bash(wget:*)"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso não bloqueia, mas te obriga a olhar cada chamada antes de acontecer. Contra uma skill que você não confia totalmente, "me pergunta sempre" já muda o jogo. O comando esquisito aparece na sua frente antes de rodar, não depois.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ninguém quer aprovar comando o dia inteiro
&lt;/h2&gt;

&lt;p&gt;Tem uma tensão real aqui, e prefiro assumir do que fingir que não existe. Esse post inteiro é sobre travar coisa, e a gente vive exatamente a era de soltar o agente, de deixar ele trabalhar meia hora sozinho e voltar com a tarefa pronta. Cada "posso rodar isso?" quebra esse fluxo. E aprovação demais vira ritual, depois da vigésima pergunta do dia você aprova sem ler. Proteção que você aprova sem ler não protege nada.&lt;/p&gt;

&lt;p&gt;A saída não é afrouxar, é mudar a decisão de lugar. O &lt;code&gt;deny&lt;/code&gt; bem feito é o que te compra liberdade no resto. Você decide uma vez, no arquivo, o que nunca pode acontecer, e solta o agente com um &lt;code&gt;allow&lt;/code&gt; generoso no dia a dia sabendo que o piso está travado. É assim que eu trabalho, o agente roda &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;npm&lt;/code&gt; e todo comando de leitura sem me perguntar, porque o que não pode já está negado. O &lt;code&gt;ask&lt;/code&gt; fica pro que é raro e de alto impacto, tipo rede pra fora. O resto é liberdade.&lt;/p&gt;

&lt;h2&gt;
  
  
  O nível mais forte é um hook que inspeciona antes de rodar
&lt;/h2&gt;

&lt;p&gt;Regra de permissão é estática, ela olha o começo do comando. Um &lt;a href="https://code.claude.com/docs/pt/hooks-guide" rel="noopener noreferrer"&gt;hook &lt;code&gt;PreToolUse&lt;/code&gt;&lt;/a&gt; é código seu que roda antes de cada ferramenta e pode olhar o comando inteiro, com toda a lógica que você quiser, e vetar.&lt;/p&gt;

&lt;p&gt;É aqui que você pega os casos que o prefix-matching não pega. Um script que recebe o comando pelo stdin, procura por qualquer padrão suspeito no texto todo, e mata com &lt;code&gt;exit 2&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;COMMAND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INPUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.tool_input.command'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# pega exfiltração independente de como foi escrita&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$COMMAND&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-qiE&lt;/span&gt; &lt;span class="s1"&gt;'(curl|wget|nc|/dev/tcp)'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Comando de rede bloqueado pelo hook. Revise manualmente."&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
  &lt;span class="nb"&gt;exit &lt;/span&gt;2
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Registra no &lt;code&gt;settings.json&lt;/code&gt; mirando os comandos Bash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"PreToolUse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"matcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$CLAUDE_PROJECT_DIR&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/.claude/hooks/guard.sh"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;code&gt;exit 2&lt;/code&gt; é o que bloqueia, e o que você escreve no stderr volta como feedback. A diferença pro &lt;code&gt;deny&lt;/code&gt; é que aqui você olha o comando inteiro com &lt;code&gt;grep&lt;/code&gt;, não só o prefixo, então &lt;code&gt;/usr/bin/curl&lt;/code&gt; e &lt;code&gt;python -c "urllib..."&lt;/code&gt; também caem se você escrever o padrão certo. E o hook compõe com as regras, não substitui. Um &lt;code&gt;deny&lt;/code&gt; continua bloqueando mesmo que o hook deixe passar, e um bloqueio do hook vence um &lt;code&gt;allow&lt;/code&gt;. As camadas se somam.&lt;/p&gt;

&lt;p&gt;Um detalhe que vale ouro. O hook roda o SEU código, então você controla 100% da lógica. Dá pra logar toda tentativa num arquivo, pedir confirmação só pra domínio desconhecido, liberar &lt;code&gt;github.com&lt;/code&gt; e barrar o resto. É o ponto onde a política deixa de ser uma lista e vira programa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quase ninguém configura a precedência dos arquivos
&lt;/h2&gt;

&lt;p&gt;Isso tudo perde o sentido se qualquer um pode sobrescrever. Os arquivos de &lt;code&gt;settings&lt;/code&gt; têm &lt;a href="https://code.claude.com/docs/pt/settings" rel="noopener noreferrer"&gt;hierarquia&lt;/a&gt;, e o de cima ganha:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Managed (política da organização, instalada como arquivo de sistema, via MDM por exemplo), não pode ser sobrescrita&lt;/li&gt;
&lt;li&gt;Argumentos de linha de comando&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.claude/settings.local.json&lt;/code&gt; do projeto (fora do git)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.claude/settings.json&lt;/code&gt; do projeto (no git)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.claude/settings.json&lt;/code&gt; do usuário&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A regra é a mesma do &lt;code&gt;deny&lt;/code&gt;. Se algo foi negado em qualquer nível, nenhum outro nível consegue liberar. &lt;/p&gt;

&lt;p&gt;Na prática isso significa duas coisas. Se você é a única pessoa da máquina, põe suas regras de proteção no &lt;code&gt;~/.claude/settings.json&lt;/code&gt;, elas valem pra todo projeto. Se você administra um time, o nível managed é onde você trava o que ninguém pode afrouxar, nem sem querer, nem de propósito.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ação prática
&lt;/h2&gt;

&lt;p&gt;Combinando as camadas, essa é uma base defensável pro cenário do comentário, uma skill de terceiro que você não auditou linha por linha. Cola no &lt;code&gt;~/.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(./.env)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(./.env.*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(~/.ssh/**)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(~/.aws/**)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Read(**/secrets/**)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ask"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(curl:*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Bash(wget:*)"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso já te dá o essencial. O dado sensível não é legível pela via mais comum, e qualquer rede pelo caminho óbvio te pede aprovação antes de rodar. Pra quem quer a camada forte, o hook &lt;code&gt;PreToolUse&lt;/code&gt; é o próximo passo, e é ele que fecha os furos que a regra de prefixo deixa aberto.&lt;/p&gt;

&lt;p&gt;Se quiser transformar isso em ação direto na sua máquina, cola este prompt no Claude Code:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Leia meu &lt;code&gt;~/.claude/settings.json&lt;/code&gt;. Some (sem apagar o que já existe) regras de &lt;code&gt;permissions.deny&lt;/code&gt; que impeçam a leitura de &lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;~/.ssh&lt;/code&gt;, &lt;code&gt;~/.aws&lt;/code&gt; e qualquer pasta &lt;code&gt;secrets&lt;/code&gt;. Me mostre o diff antes de salvar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  O que o &lt;code&gt;settings.json&lt;/code&gt; NÃO resolve
&lt;/h2&gt;

&lt;p&gt;Fecho com a parte honesta, porque parar aqui seria vender proteção completa. O &lt;code&gt;settings.json&lt;/code&gt; reduz muito o risco, mas não é uma jaula. O comando roda na sua máquina, e uma blocklist é sempre uma corrida contra quem escreve o próximo jeito de driblar.&lt;/p&gt;

&lt;p&gt;E dá pra ir um passo além. Se o segredo nem existe em arquivo, não tem o que roubar. Um gerenciador como o &lt;a href="https://www.1password.dev/cli" rel="noopener noreferrer"&gt;1Password CLI&lt;/a&gt; guarda no &lt;code&gt;.env&lt;/code&gt; só uma referência e injeta o segredo de verdade como variável de ambiente na hora de rodar, com &lt;code&gt;op run&lt;/code&gt;. O agente pode até ler o arquivo, o que tem lá é ponteiro, não chave.&lt;/p&gt;

&lt;p&gt;Pra isolamento de verdade, no nível do sistema operacional, com controle real de rede e de credencial, existe o sandbox. Por enquanto, proteja o alvo em vez da saída, deixa o &lt;code&gt;deny&lt;/code&gt; ganhar, e põe um hook no caminho crítico. É o que trava o piso uma vez e te deixa soltar o agente no resto. Já é muito mais do que a maioria das configs por aí.&lt;/p&gt;

&lt;p&gt;Como eu disse, os exemplos são do Claude Code, mas o princípio não é dele. Codex, Cursor, Gemini CLI, todo harness de IA que executa comando na sua máquina tem o mesmo tipo de trava, modo de aprovação por comando, negação de comando, algum sandbox. Os nomes de arquivo e de campo mudam, o raciocínio de "proteja o alvo, não a saída" é o mesmo em qualquer um. Aprende num, adapta pros outros.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Tech Events are NOT as cool as you think (from an organizer perspective)</title>
      <dc:creator>Keit Ollé</dc:creator>
      <pubDate>Wed, 13 Sep 2023 18:08:10 +0000</pubDate>
      <link>https://dev.to/devrelbr/tech-events-are-not-as-cool-as-you-think-from-an-organizer-perspective-2b70</link>
      <guid>https://dev.to/devrelbr/tech-events-are-not-as-cool-as-you-think-from-an-organizer-perspective-2b70</guid>
      <description>&lt;p&gt;Hello everyone! &lt;/p&gt;

&lt;p&gt;My name is &lt;strong&gt;Keit&lt;/strong&gt;, aka &lt;a href="https://twitter.com/k8adev" rel="noopener noreferrer"&gt;@k8dev&lt;/a&gt;, I'm Brazilian and, besides being a programmer, I've been organizing technology events for 8 years. &lt;/p&gt;

&lt;p&gt;I'm currently responsible for &lt;strong&gt;several technology&lt;/strong&gt; events, one of which is the renowned &lt;strong&gt;FRONTIN Sampa&lt;/strong&gt;, one of the largest and most &lt;strong&gt;traditional&lt;/strong&gt; technology events here in &lt;strong&gt;Brazil&lt;/strong&gt;, which has a great influence on the &lt;strong&gt;dev community&lt;/strong&gt;. This event takes place &lt;strong&gt;annually in July&lt;/strong&gt;, in the city of &lt;strong&gt;São Paulo&lt;/strong&gt;, where we cover a wide variety of topics related to front-end development and related areas.&lt;/p&gt;

&lt;p&gt;However, we face significant &lt;strong&gt;challenges&lt;/strong&gt;, as many people &lt;strong&gt;don't recognize&lt;/strong&gt; the &lt;strong&gt;value&lt;/strong&gt; of this type of event, and this isn't just &lt;strong&gt;limited&lt;/strong&gt; to the developer &lt;strong&gt;community&lt;/strong&gt;. If I had to &lt;strong&gt;list&lt;/strong&gt; my &lt;strong&gt;main frustrations&lt;/strong&gt; as an &lt;strong&gt;organizer&lt;/strong&gt;, they would be the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Difficulties&lt;/strong&gt; in securing sponsorship.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintaining engagement&lt;/strong&gt; before and after the event.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managing partnerships&lt;/strong&gt; and communities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The event &lt;strong&gt;FRONTIN Sampa&lt;/strong&gt; has always been an &lt;strong&gt;iconic event&lt;/strong&gt;, even before I took over the organization in &lt;strong&gt;2016&lt;/strong&gt;. However, it's important to note that without adequate &lt;strong&gt;financial resources&lt;/strong&gt;, it's &lt;strong&gt;impossible to provide a high-quality environment&lt;/strong&gt;, &lt;strong&gt;good speakers&lt;/strong&gt; and a &lt;strong&gt;competent team&lt;/strong&gt; to hold an event of this size. Here on this side of the globe, &lt;strong&gt;companies even show interest&lt;/strong&gt; in participating in events, but the &lt;strong&gt;offered sponsorship&lt;/strong&gt; values they want to give as sponsorship often &lt;strong&gt;barely cover the costs&lt;/strong&gt; they have with &lt;strong&gt;their own infrastructure&lt;/strong&gt; on the day of the event.&lt;/p&gt;

&lt;p&gt;As an example, the last FRONTIN Sampa generated approximately &lt;strong&gt;100,000.00 BRL (20,368.26 USD) in sales&lt;/strong&gt;, while &lt;strong&gt;sponsorships only amounted to around 12,000.00 BRL (2,444.04 USD)&lt;/strong&gt;, without taking barter into account. Exchanges alone are &lt;strong&gt;often unequal&lt;/strong&gt; to what we deliver during the event and on social media. Even with excellent sales, if we do a &lt;strong&gt;quick calculation&lt;/strong&gt;, it's clear that the &lt;strong&gt;equation doesn't add up&lt;/strong&gt;. Organizing events like &lt;strong&gt;FRONTIN Sampa&lt;/strong&gt; requires not only resources for the day of the event, but  there are &lt;strong&gt;efforts and resources&lt;/strong&gt; needed before and after the event that are usually not accounted for. Here at FRONTIN, the company I set up to manage events, we have a number of needs such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Social media management&lt;/li&gt;
&lt;li&gt;Graphic design&lt;/li&gt;
&lt;li&gt;Sales&lt;/li&gt;
&lt;li&gt;Content production&lt;/li&gt;
&lt;li&gt;Marketing&lt;/li&gt;
&lt;li&gt;Subscriptions to services such as Mailchimp, Google Workspace, Figma, Canvas, among others&lt;/li&gt;
&lt;li&gt;Event management&lt;/li&gt;
&lt;li&gt;Partnership and sponsorship management&lt;/li&gt;
&lt;li&gt;Public relations&lt;/li&gt;
&lt;li&gt;Accounting management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And so on and so forth.&lt;/p&gt;

&lt;p&gt;It's &lt;strong&gt;almost a year of planning and execution&lt;/strong&gt;, with &lt;strong&gt;monthly costs&lt;/strong&gt; that are &lt;strong&gt;impossible&lt;/strong&gt; to meet &lt;strong&gt;without sponsorship&lt;/strong&gt; or personal investment. And yes! Sometimes the organizers &lt;strong&gt;have to take money out of their own pockets&lt;/strong&gt; because, once again, &lt;strong&gt;the equation doesn't add up&lt;/strong&gt;. We're talking about around 10,000.00 BRL or more to maintain the structure and team needed to produce the event, monitor social media, manage the community, communicate and other activities.&lt;/p&gt;

&lt;p&gt;We're talking about around &lt;strong&gt;170,000.00 BRL or 34,000 USD&lt;/strong&gt; to produce FRONTIN Sampa this year!&lt;/p&gt;

&lt;p&gt;On the other hand, we have an &lt;strong&gt;audience&lt;/strong&gt; who often &lt;strong&gt;complains about the ticket prices&lt;/strong&gt;. We &lt;strong&gt;always&lt;/strong&gt; try to offer extremely &lt;strong&gt;affordable tickets&lt;/strong&gt; — which are usually &lt;strong&gt;not compatible&lt;/strong&gt; with an &lt;strong&gt;event&lt;/strong&gt; of such &lt;strong&gt;high standards&lt;/strong&gt;, specially in the middle of a recession. We implemented &lt;strong&gt;strategies&lt;/strong&gt; such as &lt;strong&gt;selling tickets&lt;/strong&gt; in advance and &lt;strong&gt;offering half-price&lt;/strong&gt; tickets to make the event as accessible as possible. However, it's not uncommon to come across people who don't recognize the hard work behind organizing the event and make unconstructive criticisms publicly.&lt;/p&gt;

&lt;p&gt;When it comes to &lt;strong&gt;partnerships&lt;/strong&gt;, &lt;strong&gt;communities&lt;/strong&gt; and tech &lt;strong&gt;influencers&lt;/strong&gt;, many of them are more &lt;strong&gt;interested in the coupons and free tickets&lt;/strong&gt; they receive &lt;strong&gt;than in actually helping to publicize&lt;/strong&gt; events and build an &lt;strong&gt;environment&lt;/strong&gt; where people can &lt;strong&gt;learn&lt;/strong&gt;, &lt;strong&gt;share&lt;/strong&gt; and &lt;strong&gt;have fun&lt;/strong&gt;. What's more, managing these partnerships is often complicated, as it involves an exchange relationship. Once again, &lt;strong&gt;the lack of financial&lt;/strong&gt; resources affects our ability to give proper attention to these partnerships and to follow up on the fulfillment of obligations on both sides.&lt;/p&gt;

&lt;p&gt;This year has been &lt;strong&gt;particularly challenging&lt;/strong&gt;, with &lt;strong&gt;few financial resources&lt;/strong&gt; and &lt;strong&gt;many&lt;/strong&gt; events to be held to meet the &lt;strong&gt;community's expectations&lt;/strong&gt;. It was so &lt;strong&gt;difficult&lt;/strong&gt; that I was &lt;strong&gt;forced&lt;/strong&gt; to put practically &lt;strong&gt;ALL MY MONEY&lt;/strong&gt; into FRONTIN to &lt;strong&gt;ensure&lt;/strong&gt; that all the &lt;strong&gt;events took place&lt;/strong&gt; even though I didn't raise &lt;strong&gt;enough funds&lt;/strong&gt;. This has &lt;strong&gt;made me rethink several times&lt;/strong&gt; whether it is &lt;strong&gt;worth continuing to produce these events&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I'm looking &lt;strong&gt;forward to hearing the perspective&lt;/strong&gt; of other people who &lt;strong&gt;actively or voluntarily work&lt;/strong&gt; on &lt;strong&gt;tech events&lt;/strong&gt;. I'd love to talk to you and maybe find some &lt;strong&gt;motivation&lt;/strong&gt; to keep going, or even companies to be joining us in the next event. I believe that our work is fundamental to &lt;strong&gt;creating an environment&lt;/strong&gt; where people can connect and I truly don't want to give up.&lt;/p&gt;

&lt;p&gt;Thank you!&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>techtalks</category>
      <category>braziliandevs</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
