Harness de revisão estática de segurança de aplicações multiagente para agentes de codificação com IA: mapeia bases de código, caça classes de vulnerabilidade, encadeia e verifica descobertas e reporta em SARIF, JSON e PDF.
Um harness de revisão de segurança de aplicações multiagente para o Claude Code (e, posteriormente, outros agentes de IA). Uma skill de roteamento despacha para um pipeline completo de segurança ofensiva que mapeia uma base de código, caça vulnerabilidades com uma base de conhecimento por classe, encadeia descobertas em escalonamentos, verifica o impacto real e reporta para README / JSON / SARIF / doc / PDF.
Escopo: este harness realiza análise estática (revisão de código-fonte, rastreamento de fluxo de dados, construção de PoC/payload) em código que você possui ou está autorizado a testar. Ele não ataca sistemas terceiros em produção.
security-harness/ # a plugin marketplace └── plugins/security-harness/ ├── skills/ │ ├── sh-router # single entry point - routes any appsec request │ ├── sh-security-review # the pipeline orchestrator (Stages 0-5) │ └── sh-kb-* (15) # per-vuln-class knowledge bases ├── agents/ │ ├── sh-recon # map: Graft graph + stack/SBOM/CVE + attack surface │ ├── sh-hunter # find: source→sink hunting, one per class (parallel) │ ├── sh-chainer # escalate: combine findings into attack chains │ ├── sh-verifier # confirm: offensive + seceng + dev verification + PoC │ └── sh-reporter # deliver: README/JSON/SARIF/HTML/PDF/doc └── references/ # shared contracts (finding schema, SARIF map, state files, rubrics)
### Classes de vulnerabilidade cobertas (as skills `sh-kb-*`)
access-control (IDOR/BOLA/priv-esc) · sqli · xss · ssrf · injection (cmd/code/SSTI/LDAP) · auth (session/JWT)
· deserialization · path-traversal (LFI/RFI) · secrets · csrf · xxe · open-redirect · crypto · race-conditions
· file-upload. CVEs de dependências/SBOM são tratados pelo estágio de recon.
## Instalação
O harness é distribuído para vários agentes. Detalhes completos de empacotamento e a checklist
de release estão em [`docs/DISTRIBUTION.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/docs/DISTRIBUTION.md).
**Claude Code** - adicione este repositório como um marketplace de plugins e instale o plugin:```
/plugin marketplace add dmdhrumilmistry/security-harness
/plugin install security-harness
/plugin marketplace add aceita qualquer um dos seguintes: um owner/repo do GitHub (como acima), uma URL git completa
(https://github.com/dmdhrumilmistry/security-harness.git), ou um caminho local para um clone
(por exemplo, /plugin marketplace add ./security-harness a partir do diretório que contém o seu checkout).
Em seguida, execute /plugin install security-harness e recarregue quando solicitado.
Gemini CLI - uma extensão nativa, com manifesto na raiz do repositório:```bash gemini extensions install https://github.com/dmdhrumilmistry/security-harness
**opencode, Codex, ou qualquer agente [agentskills.io](https://agentskills.io)** - copie as
skills para um diretório de descoberta. O Codex adicionalmente captura `AGENTS.md` por conta própria:```bash
git clone https://github.com/dmdhrumilmistry/security-harness
cd security-harness
python3 scripts/sync-agent-skills.py --install agents # ~/.agents/skills
python3 scripts/sync-agent-skills.py --install opencode # ~/.config/opencode/skills
O Graft é instalado e configurado automaticamente pelo pipeline. O Estágio 0 executa npm install -g @nanonets/graft se estiver em falta (requer Node/npm), depois graft init <target> --no-agents --no-global
para registar o servidor MCP do Graft e os hooks de frescura para o repositório alvo. O grafo em si (<target>/graft/,
auto-gitignored) é construído durante o recon. Para pré-instalar manualmente: npm install -g @nanonets/graft. A construção
estrutural do Graft é gratuita e não precisa de chave de API; a passagem LLM opcional --deep usa GRAFT_API_KEY /
GRAFT_PROVIDER / GRAFT_MODEL quando definidos.
As outras ferramentas também são auto-instaladas pelo Estágio 0 quando em falta (através do gestor de pacotes que estiver na
máquina - winget/choco/scoop, brew, apt, npm/pip/go - ver references/tooling-setup.md). As instalações são
anunciadas, preferem métodos sem elevação e nunca bloqueiam a execução: tudo o que não puder ser instalado é simplesmente
marcado como indisponível e o pipeline recorre a alternativas. O Estágio 0 instala apenas o que preenche um grupo de capacidades em falta:
syft · CVEs: um de grype
(preferido), trivy, ou osv-scannerwkhtmltopdf ou pandoc (para PDF/DOCX); caso contrário obtém report.html (ou um PDF headless-Chrome).Todos eles são opcionais - o pipeline degrada graciosamente para pesquisa nativa + análise de manifestos se nenhum for instalado.
Invoque o router com um pedido em linguagem natural:``` /sh-router full security review of ./api /sh-router find SQLi and IDOR in src/ /sh-router just map this codebase # recon only
Ou chame o pipeline diretamente:```
/sh-security-review . classes:sqli,access-control,ssrf depth:deep
/sh-security-review . stage:report # regenerate reports for the latest run
Cada estágio é executado em um modelo adequado à sua carga cognitiva, de modo que os tokens são gastos onde a qualidade da descoberta realmente depende deles e economizados em trabalho mecânico. Este é o padrão - nenhum argumento necessário.
| Estágio | Modelo padrão |
|---|---|
| recon | sonnet |
| hunt (por classe) | haiku para classes de padrão (secrets, crypto, open-redirect, csrf) · sonnet para rastreamento source→sink (sqli, xss, ssrf, injection, path-traversal, xxe, file-upload, auth) · opus para classes de lógica profunda (access-control, race-conditions, deserialization) |
| chain | opus |
| verify | opus (o portão de precisão - mantido forte) |
| report | haiku |
Substitua com o argumento models: (também passado pelo router):```
/sh-security-review . # default tiered map above
/sh-security-review . models:max # every stage + hunter on opus (max quality, max cost)
/sh-security-review . models:cheap # aggressive downshift (trades some verify precision)
/sh-security-review . models:verify=opus,hunt=sonnet # per-stage overrides
/sh-security-review . models:report=sonnet,hunt.pattern=sonnet # per-hunter-tier override
Estágios: `setup, recon, hunt, chain, verify, report`. Modelos: `opus, sonnet, haiku, inherit`. Para `hunt`,
um modelo simples nivela todos os hunters para ele; `hunt.pattern` / `hunt.trace` / `hunt.logic` visam um nível.
Outros economizadores de tokens são incorporados: o recon só gera hunters para classes com superfície de ataque real, os hunters
consultam o grafo Graft em vez de ler arquivos inteiros, e `findings.json`/SARIF são gerados por um
script determinístico em vez do modelo.
### Saída
Tudo fica em `<target>/.security-harness/<run-id>/`:
- `recon.md`, `codebase-map.json` - o mapa (stack, SBOM, CVEs, superfície de ataque).
- `findings.jsonl` → `chains.md` → `verified.jsonl` - o estado de trabalho (veja `references/state-files.md`).
- `reports/` - `README.md`, `findings.json`, `results.sarif`, `report.html`, `report.pdf` (+ `report.docx`).
Cada achado publicado carrega um payload, um PoC, o veredito de verificação, ids CWE/OWASP, CVSS e uma
mitigação em nível de código.
## Revisão de pull request
`sh-pr-review` revisa um único pull request em vez de todo um codebase, publica o
resultado como comentários inline **no próprio PR**, e define um status de commit `security/pr-review`
que a proteção de branch pode impor.
**Execute-o da sua própria máquina, em qualquer PR que você possa ler.** Instale o plugin e pergunte:```
review https://github.com/acme/api/pull/128
review PR 42
security review this PR
Cole um link de PR e ele revisa esse PR naquele repositório, clonando-o primeiro para um diretório temporário, porque os hunters leem arquivos e não apenas o patch. Nada é escrito no repositório em que você está trabalhando.
Passe um número simples e ele é resolvido em relação ao repositório em que você está atualmente, aquele para o qual o git remote aponta. Não passe nada e ele pega o PR aberto para o seu branch atual.
A Fase 7 imprime os achados e o veredito e pergunta antes de postar qualquer coisa - uma recusa é um resultado normal, e o payload permanece no disco para você postar depois.
Antes de gastar qualquer análise, ele verifica se você realmente pode escrever no repositório de destino, então revisar o projeto de outra pessoa informa de antemão que a postagem retornará 403 em vez de descobrir isso dez minutos depois.
Três propriedades o tornam utilizável como um merge gate em vez de ruído:
pr_impact de introduced, aggravated ou pre_existing. Os dois primeiros bloqueiam; pre_existing é reportado e nunca bloqueia. Bloquear um merge por causa de código que o autor nunca escreveu é como um check obrigatório acaba sendo removido, então quando um hunter está em dúvida entre aggravated e pre_existing, ele deve escolher pre_existing.sh-kb-* usam, e então escolhe um tier. O Tier 0 (nenhuma mudança relevante para segurança) não lança nada e ainda assim define o status. O Tier 3 executa o pipeline completo.| Verdict | Status | Quando |
|---|---|---|
| fail | failure | achado introduced ou aggravated igual ou acima de --fail-on (padrão medium), confiança >= 80 |
| warn | success | nada introduced ou aggravated; achados pre-existing reportados |
| pass | success | nenhum achado, ou o triage parou no Tier 0 |
| error | error | a revisão não pôde ser concluída |
warn reporta success de propósito: um aviso que bloqueia um merge é uma falha com etapas extras, e as equipes respondem removendo o check. error é mantido distinto de failure para que uma execução quebrada nunca pareça uma vulnerabilidade que ela não encontrou.
O evento de revisão é sempre COMMENT, nunca REQUEST_CHANGES ou APPROVE. O commit status é o mecanismo de enforcement, e é o que a branch protection lê.
Escopo: a skill escreve no pull request e no commit status, e em nenhum outro lugar. Ela não abre issues e não cria nada em nenhum tracker externo.
Um PR é revisado uma vez por push, então a segunda revisão precisa ser mais barata que a primeira ou a ferramenta se torna algo que as pessoas desligam.
A deduplicação acontece antes do gasto, não antes da postagem. As fingerprints já presentes no PR são lidas na Fase 1 e entregues aos hunters e ao verificador. Encontrar um duplicado no final significaria que o modelo mais caro do pipeline já teria reconfirmado uma conclusão que estava escrita no PR o tempo todo. Isso não precisa de cache: o estado vive no PR, então funciona em uma máquina fria e em CI.
Um cache local torna o resto incremental. O sh-review-cache armazena os hashes de arquivos, achados e vereditos de cada execução no diretório de cache do seu SO (nunca no repositório, já que uma revisão cross-repo roda em um clone temporário que é excluído). A próxima revisão re-caça apenas arquivos cujo conteúdo realmente mudou, reutiliza vereditos para achados que não mudaram e reutiliza o mapa de recon se nada que ele cobre se moveu.
Um merge da branch base não custa nada. Fazer merge de main em um branch de PR altera o head SHA e nada do que o autor escreveu, mas um commit status é fixado a um SHA, então o check obrigatório desaparece silenciosamente do novo head. Quando os arquivos do próprio PR são byte-idênticos e o delta da base não toca em nada do que os achados dependem, o veredito anterior é re-carimbado no novo SHA sem nenhum agente lançado. Essa última condição é o que o torna seguro: um merge da base que remove um sanitizer deixa todos os arquivos do PR inalterados enquanto transforma uma linha segura em uma explorável.
A invalidação é deliberadamente conservadora, porque uma entrada obsoleta em uma ferramenta de segurança não a torna lenta, torna-a errada. A chave de cache faz hash de toda base de conhecimento sh-kb-*, então uma atualização de KB invalida todo achado em cache - um "clean" em cache nunca deve suprimir o achado que aquela atualização foi escrita para capturar. Identidade do modelo, versão da skill, conteúdo do arquivo e um TTL de 7 dias também invalidam, e um modelo não especificado é tratado como miss.
--no-cache desativa isso, --refresh-cache re-baselineia, e run.md registra por fase o que foi lançado, reutilizado e ignorado, para que um cache que silenciosamente para de acertar seja visível em vez de presumido.
A revisão e o commit status são postados por padrão. Uma revisão que foi computada e nunca entregue não ajudou ninguém. --confirm restaura um prompt antes de postar, --dry-run não envia nada, --no-status posta a revisão mas deixa o commit status em paz.
A postagem passa por scripts/sh-pr-post.py em vez de chamadas de API construídas à mão, porque é uma operação de múltiplas etapas com uma cauda obrigatória: revisão, depois status, depois recibos, com um 422 recuperado movendo o comentário em vez de deslocar um número de linha. O script nunca sai deixando o status em pending - se a revisão não puder ser postada, ele ainda define error, dizendo que o tooling falhou em vez de acusar o PR.
Comentários inline são reservados para achados de medium ou acima com confiança >= 80. Achados de baixa severidade vão na seção de corpo recolhida, então um achado de baixa prioridade aparecendo com zero comentários inline é a política funcionando, não uma falha.
Cada execução registra quanto custou, para que "o cache está funcionando" e "as revisões ficaram mais lentas" deixem de ser questões de opinião.```bash python3 /scripts/sh-metrics.py path # where records live python3 /scripts/sh-metrics.py report # aggregate, by model python3 /scripts/sh-metrics.py purge --older-than-days 30
Dois arquivos JSONL somente de acréscimo - `runs.jsonl` (repo, PR, tier, veredito, totais, os flags que você
passou) e `events.jsonl` (uma linha por fase ou agente: modelo, tokens, duração, resultado,
se foi reutilizado do cache). JSONL para que uma execução que falhou ainda deixe linhas válidas acima
da falha.
| Plataforma | Métricas | Cache |
|---|---|---|
| **Linux / BSD** | `$XDG_DATA_HOME/security-harness/metrics`<br>padrão `~/.local/share/security-harness/metrics` | `$XDG_CACHE_HOME/security-harness`<br>padrão `~/.cache/security-harness` |
| macOS | `~/Library/Application Support/security-harness/metrics` | `~/Library/Caches/security-harness` |
| Windows | `%LOCALAPPDATA%\security-harness\metrics` | `%LOCALAPPDATA%\security-harness\cache` |
O Linux segue a especificação XDG Base Directory, então ambos respeitam `XDG_DATA_HOME` e
`XDG_CACHE_HOME` quando definidos e recorrem a `~/.local/share` e `~/.cache` quando
não estão. Substitua qualquer um diretamente com `SH_METRICS_DIR` e `SH_REVIEW_CACHE_DIR`.
**Sobre `python` vs `python3`:** a maioria das distribuições Linux traz `python3` e não tem `python`
nenhum, então os exemplos aqui usam `python3`. Os scripts incluídos carregam um
shebang `#!/usr/bin/env python3` e são executáveis, então `./scripts/sh-metrics.py report`
funciona diretamente no Linux e macOS. A skill resolve
`PY="$(command -v python3 || command -v python)"` uma vez por execução, o que cobre as três
plataformas, incluindo Git Bash no Windows.
**Estritamente local.** Nenhum dos scripts contém qualquer código de rede ou endpoint de relatório.
Qualquer coisa com formato de token é redigida antes de ser escrita, porque arquivos locais acabam colados
em issues.
### Executando sem supervisão
Opcional, e uma decisão separada do uso da skill. Execute manualmente nos seus próprios PRs
por um tempo primeiro, para que você saiba o que ela diz sobre sua base de código antes que ela diga
na frente da sua equipe.
Quando estiver pronto, "Enforcing the check on a repository" em
[`references/pr-review-mapping.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/plugins/security-harness/references/pr-review-mapping.md)
tem um workflow de copiar e colar para o **seu** repositório, além do fail-safe que impede que um job morto
deixe uma verificação obrigatória presa em `pending`.
O limiar permanece no padrão `medium`. Achados pré-existentes nunca bloqueiam um merge,
então uma base de código não escaneada não produz uma parede de vermelho no primeiro dia - apenas o que um PR
realmente introduz ou agrava pode reprová-lo.
## Como funciona
1. **Setup** - sondar ferramentas disponíveis, definir escopo, criar o diretório de execução.
2. **Recon** (`sh-recon`) - construir o grafo Graft; detectar stack/versões; SBOM + CVEs; enumerar pontos
de entrada, limites de confiança e sinks perigosos.
3. **Hunt** (`sh-hunter` ×N, paralelo) - um hunter por classe relevante carrega sua base de conhecimento `sh-kb-*`,
rastreia a entrada do atacante da origem ao sink e registra candidatos. Um **ledger de tentativas** compartilhado impede
que os agentes repitam as sondagens uns dos outros.
4. **Chain** (`sh-chainer`) - compor achados em caminhos de ataque de maior severidade.
5. **Verify** (`sh-verifier`) - refutar primeiro, depois confirmar a explorabilidade a partir de evidências, construir PoCs, atribuir
CVSS e cortar falsos positivos.
6. **Report** (`sh-reporter`) - produzir os entregáveis.
Os subagentes não compartilham nada além de arquivos; o contrato está em `plugins/security-harness/references/state-files.md`.
## Estendendo
Adicione uma nova classe de vulnerabilidade criando `skills/sh-kb-<class>/SKILL.md` seguindo o template compartilhado
(When to hunt · Sources & sinks · Detection recipe · Payloads/PoC · False-positive filters · CWE/OWASP ·
Chaining hints · Mitigation), depois adicione seu slug ao enum `class` em `references/finding-schema.json`
e à tabela de roteamento em `skills/sh-router/SKILL.md`.
## Atualizações automatizadas da base de conhecimento
Uma GitHub Action agendada (`.github/workflows/update-knowledge-base.yml`) mantém as bases de conhecimento `sh-kb-*`
atualizadas. **A cada dois dias** (e em `workflow_dispatch` manual), ela executa um agente para destilar novas
pesquisas de segurança públicas e confiáveis - OWASP, PortSwigger Research, CWE/CAPEC, NIST, MDN, repositórios
GitHub curados e divulgações públicas do HackerOne - em pequenas melhorias bem fundamentadas. Um **segundo agente
revisor, adversarial**, então escaneia o diff resultante em busca de conteúdo malicioso/injetado, e o PR é
**mesclado automaticamente apenas se esse revisor aprovar**.
### Dois workflows, três jobs
A criação do PR é deliberadamente separada da revisão e do merge, para que a coisa que escreve
o diff nunca seja a coisa que decide enviá-lo.
**Estágio 1 - [`update-knowledge-base.yml`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/workflows/update-knowledge-base.yml)**
(agendado ou manual). Um job, `create-pr`:
1. **Generate** - o agente edita a KB a partir de fontes permitidas. Sem commit, sem push.
2. **Open PR** - um passo determinístico abre (ou atualiza) um PR no branch `automated/kb-update`,
rotulado `awaiting-review`.
3. **Hand off** - em uma criação de PR bem-sucedida, ele despacha o estágio 2 com o número do PR.
**Estágio 2 - [`kb-review-and-merge.yml`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/workflows/kb-review-and-merge.yml)**
(despachado pelo estágio 1, ou executado manualmente contra qualquer PR automatizado). Dois jobs:
- **`review`** - uma execução de agente *separada* inspeciona o diff **adversarialmente** em busca de
artefatos de prompt-injection, edições fora de escopo, segredos/exfiltração, PII, exploits
weaponizados, origem fora da allowlist ou violações do estilo da casa. Ele **não tem web nem
shell**, e **falha fechado**: qualquer coisa suspeita, qualquer incerteza ou um arquivo de
veredito ausente → REJECT. O veredito é postado como comentário no PR e direciona o rótulo.
- **`merge`** - executa **apenas** em `APPROVE`, e mescla o PR. Um `REJECT` o pula e
o job `blocked` relata o motivo.
> **Por que um dispatch em vez de um gatilho `pull_request`:** um PR aberto por `GITHUB_TOKEN`
> não dispara workflows `pull_request`. `workflow_dispatch` é um dos dois eventos
> isentos dessa proteção de recursão, então o estágio 1 pode fazer o hand off de forma confiável.
**Auto-merge significa que um agente aprovador coloca código em `main`.** Os controles sobre isso:
- O job de merge recusa qualquer PR que esteja fechado, seja de um fork, ou cujo branch head esteja
fora de `automated/*` (`ALLOWED_HEAD_PREFIX` no workflow).
- Ele prefere o auto-merge do próprio GitHub, então **a proteção de branch ainda se aplica**. Com uma regra
em `main` exigindo uma revisão aprovadora, o PR entra na fila e espera por um humano em vez de
mesclar. Ele recorre a um merge imediato apenas em repositórios onde o auto-merge está desativado.
- Defina a entrada `auto_merge` como `false` em uma execução manual para revisar sem mesclar.
- O prompt do revisor diz ao agente que seu veredito é vinculante, não consultivo.
> Requer a configuração do repositório **"Allow GitHub Actions to create and approve pull requests"** (Settings →
> Actions → General → Workflow permissions) para que o workflow possa abrir o PR. Se você quiser um humano no
> loop apesar do auto-merge, proteja `main` com uma regra de proteção de branch exigindo um pull request e pelo
> menos uma revisão aprovadora - o caminho de auto-merge a respeita.
### Agentes plugáveis
Ambos os estágios executam através de [`.github/actions/ai-agent`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/actions/ai-agent/action.yml),
uma ação composta que despacha para qualquer agente que você configurar. Claude Code, OpenAI
Codex, Gemini CLI e uma saída de emergência para qualquer outra coisa:
| `agent` | Executa | Credencial |
|---|---|---|
| `claude` (padrão) | `anthropics/claude-code-action@v1` | `CLAUDE_CODE_OAUTH_TOKEN` ou `ANTHROPIC_API_KEY` |
| `codex` | `codex exec --full-auto` | `OPENAI_API_KEY` |
| `gemini` | `gemini --yolo --prompt` | `GEMINI_API_KEY` |
| `custom` | seu `KB_AGENT_INSTALL` / `KB_AGENT_COMMAND` | o que for necessário |
Escolha por execução a partir das entradas de `workflow_dispatch`, ou defina variáveis de repositório para alterar o
padrão: `KB_AGENT` e `KB_MODEL` para o gerador, `KB_REVIEW_AGENT` e
`KB_REVIEW_MODEL` para o revisor. Executar o gerador e o revisor em **agentes
diferentes** é um passo de hardening significativo: uma injeção ajustada para um modelo tem menos probabilidade
de acertar um segundo, independente.
Para `agent: custom`, defina `KB_AGENT_COMMAND` como um comando shell. O prompt é escrito no
arquivo nomeado por `$AGENT_PROMPT_FILE`, e `$AGENT_MODEL` carrega a entrada do modelo.
Defesas contra prompt-injection, já que o gerador lê a web aberta:
- **Allowlist de domínios.** `WebFetch` é restrito aos domínios confiáveis em
`.github/kb-update/trusted-sources.md` (espelhado no `--allowedTools` do workflow). `WebSearch` pode
descobrir URLs, mas apenas domínios na allowlist podem de fato ser buscados.
- **Conteúdo é dado, não comandos.** O prompt da tarefa (`.github/kb-update/prompt.md`) instrui o Claude a
tratar cada byte buscado como material de referência não confiável e a ignorar quaisquer instruções embutidas em uma
página - corpos de relatórios do HackerOne (gerados por usuários) são sinalizados como o nível de maior risco.
- **Sem shell, sem push no gerador; o revisor é o portão.** O gerador só pode editar arquivos.
O revisor independente (`.github/kb-update/review-prompt.md`) é o que fica entre o conteúdo buscado
e `main` - nada é mesclado sem sua aprovação explícita.
- **Agentes diferentes para gerador e revisor.** Opcional, e a versão mais forte do portão: defina
`KB_AGENT` e `KB_REVIEW_AGENT` para dois motores diferentes.
**Configuração:**
- Adicione a credencial para qualquer agente que você usar (Settings → Secrets and variables → Actions):
**`CLAUDE_CODE_OAUTH_TOKEN`** (padrão), `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` ou `GEMINI_API_KEY`.
O token OAuth autentica contra **os limites de uso da sua assinatura Claude** em vez de uma chave de API
medida - gere-o localmente com `claude setup-token` (requer uma assinatura Claude Pro/Max ativa)
e cole o resultado.
- Ative **"Allow GitHub Actions to create and approve pull requests"** (Settings → Actions → General →
Workflow permissions) para que o workflow possa abrir seu PR. Recomendado: adicione uma regra de proteção de branch em `main`
exigindo um PR e uma revisão aprovadora, para que nenhuma alteração automatizada possa entrar sem um humano mesmo com
auto-merge ativado.
- Para alterar quais fontes são permitidas, edite a allowlist em `trusted-sources.md` **e** as entradas
`WebFetch(domain:...)` correspondentes no workflow - mantenha as duas em sincronia.
Cada execução registra o que fez em `.github/kb-update/last-run-summary.md`.
## Roadmap
- ~~Fiação de espelhamento para Codex / Cursor.~~
✅ Entregue: `AGENTS.md`, uma extensão do Gemini CLI e `scripts/sync-agent-skills.py`
para `.agents/skills` e opencode. Veja [`docs/DISTRIBUTION.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/docs/DISTRIBUTION.md).
- ~~Aumento opcional de busca ao vivo das bases de conhecimento (PortSwigger/OWASP/CWE) sobre as referências curadas.~~
✅ Entregue como o atualizador agendado da base de conhecimento acima.
- Ponte DAST opcional para confirmação em tempo de execução de achados `needs-runtime`.
## Licença
MIT