Era inofensivo quando você instalou: criando a impressão digital das suas skills de agent


Três meses atrás você instalou uma skill de PDF. Ela continua convertendo PDFs numa boa — só que agora o diretório tem um fetch_helper.sh que nunca teve, e o SKILL.md ganhou uma linha que baixa um script de um IP desconhecido. O marketplace de skills auditou aquilo uma vez, no momento da publicação. Desde então esses arquivos vivem no seu disco, onde o repositório upstream, um script de auto-update ou um git pull distraído podem reescrevê-los. O skill-integrity existe exatamente para essa janela: ele não julga o conteúdo, ele te diz quais bytes se moveram.

“Eu instalei, então é seguro” é uma ilusão

Uma skill de agent é uma pasta — um SKILL.md mais alguns scripts e assets. O Hermes lê de ~/.hermes/skills/; o Claude Code lê de ~/.claude/skills/. Não existe verificação de assinatura nem lock de versão. O pessoal de segurança chama a classe de ataque resultante de rug-pull: inofensiva na instalação, reescrita em silêncio depois que conquistou sua confiança — uma chamada de saída adicionada, uma URL de download trocada, um script que lê o seu ambiente.

Duas propriedades dessa mudança são exatamente o que o hash pega: ela sempre altera os bytes do arquivo, e normalmente mexe em pouquíssimos arquivos.

A menor coisa útil que ele faz

O skill-integrity calcula um SHA-256 para cada arquivo de cada diretório de skill, grava o resultado como um manifesto de snapshot e então recalcula e faz o diff a cada verificação:

skills scanned: 23  (snapshot taken 2026-10-10T21:44:32+0800)

[~] pdf-extractor — MODIFIED
    changed: SKILL.md
    added:   fetch_helper.sh

1 skill(s) changed since snapshot. Review diffs before trusting them.

Detalhes que valem saber:

  • Ele varre ~/.hermes/skills e ~/.claude/skills por padrão e registra quais diretórios um snapshot cobriu — as execuções seguintes de check reaproveitam isso, então uma divergência de diretórios não gera uma parede de entradas falsas de “removed”.
  • Arquivos acima de 512KB são pulados, assim como __pycache__, node_modules e .git. Quantos foram pulados, e quais em cada skill, é impresso, nunca escondido.
  • Um diretório de skill que não pode ser aberto é reportado como finding, nunca como varredura limpa e vazia — uma skill ilegível é justamente onde uma modificação se esconderia.
  • Os códigos de saída têm significado: 0 limpo, 1 findings, 2 sem snapshot ainda ou erro de uso. O --no-fail-on-change força 0 enquanto você ainda está avaliando.
  • O manifesto fica em modo 0600, só local, zero chamadas de rede.

Instale, depois tire a linha de base

Ele está no catálogo curado (skill-integrity, nível community, exige Hermes >= 0.21.6). Se o catálogo do seu build lista a entrada, instale pelo nome:

hermes plugins install skill-integrity
hermes plugins enable skill-integrity

Se o seu catálogo ainda não sincronizou essa entrada, instale a partir do repositório como o README descreve:

git clone https://github.com/ZidoCode/skill-integrity ~/.hermes/plugins/skill-integrity
hermes plugins enable skill-integrity

Depois faça a única coisa que todo mundo esquece — tire uma linha de base, senão a checagem não tem com o que comparar e fica em silêncio para sempre:

/skill-integrity snapshot   # registra a linha de base que o hook horário lê
/skill-integrity check      # diff em nível de arquivo contra o snapshot
/skill-integrity show       # resumo do snapshot

Você também pode rodar standalone, como um único arquivo sem dependências (Python 3.8+):

python3 skill_integrity.py snapshot
python3 skill_integrity.py check --json

Os dois caminhos guardam o estado em lugares diferentes: o plugin escreve ~/.hermes/plugin-data/skill-integrity/manifest.json, e o CLI standalone usa ~/.skill-integrity/manifest.json por padrão. Aponte o CLI para o estado do plugin com --state-dir:

python3 skill_integrity.py --state-dir ~/.hermes/plugin-data/skill-integrity check --json

Deixe o agent vigiar as próprias skills

O plugin registra um hook pre_llm_call que roda mais ou menos a cada hora e injeta no contexto do agent apenas os nomes das skills alteradas. Execuções limpas não dizem nada, então você não tem ruído — nem falsa sensação de segurança.

Prefere um timer externo? Uma entrada de cron resolve:

0 */12 * * * python3 ~/skill-integrity/skill_integrity.py check --json >> ~/.skill-integrity/checks.log

Decida onde esse log vive e quem consegue lê-lo; o guia de limites de session é uma boa introdução a esse tipo de higiene.

Os limites que ele admite

Ferramentas assim são perigosas quando são confundidas com um certificado de segurança, então o README declara as fronteiras — e vale repeti-las:

  • Hashes provam que os bytes mudaram, não a intenção. Uma atualização legítima do upstream e uma reescrita maliciosa parecem idênticas. Você recebe o gatilho e a lista de arquivos; ler o diff é a sua metade do contrato.
  • Ele não reescreve snapshots históricos. Quem tem acesso de escrita pode refazer o snapshot por cima dos próprios rastros — o snapshot é gravável pelo agent por design.
  • Conteúdo malicioso dentro de um arquivo inalterado? Fora do escopo. Isso é trabalho de varredura de conteúdo.
  • É uma ferramenta de integridade de inventário, não antivírus. Arquivos acima de 512KB e symlinks são pontos cegos — contados, mas não rastreados.

Então trate como um lembrete de checkup, não como detector de metais.

Uma rotina que realmente se sustenta

  1. Snapshot logo depois de instalar skills. Uma linha de base tirada uma semana depois é a linha de base das mudanças de outra pessoa.
  2. Cheque depois de todo upgrade de skill ou pull do upstream, revise o diff e então refaça o snapshot.
  3. Quando aparece um finding, siga esta ordem: leia o diff e confirme que não foi você que escreveu; pergunte o que a skill consegue alcançar (arquivos? rede? variáveis de ambiente?); na dúvida, desative e mova o diretório para fora; se ela pode ter lido credenciais, rotacione essas chaves com o playbook de higiene de credenciais.
  4. Em setups com vários profiles, o plugin deriva os diretórios de skill e de estado de get_hermes_home(), então profiles não padrão são cobertos — mas cada profile mantém o próprio snapshot.

Para o ecossistema mais amplo, comece por como o catálogo de plugins funciona e pela referência de hermes plugins. O mesmo autor também publica um janitor de processos e um ledger de segurança; a ideia comum é prestar contas do que um agent deixa para trás.