Harness di revisione statica della sicurezza delle applicazioni multi-agente per agenti di coding AI: mappa le codebase, caccia classi di vulnerabilità, concatena e verifica i risultati e genera report in SARIF, JSON e PDF.
Un harness multi-agente per la revisione della sicurezza applicativa per Claude Code (e, in seguito, altri agenti AI). Una skill router smista verso una pipeline completa di sicurezza offensiva che mappa una codebase, caccia vulnerabilità con una knowledge base per classe, concatena i risultati in escalation, verifica l'impatto reale e riporta su README / JSON / SARIF / doc / PDF.
Ambito: questo harness esegue analisi statica (revisione del codice, tracciamento del flusso di dati, costruzione di PoC/payload) su codice di tua proprietà o che sei autorizzato a testare. Non attacca sistemi terzi live.
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)
### Classi di vulnerabilità coperte (le skill `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. Le CVE delle dipendenze/SBOM sono gestite dalla fase di recon.
## Installazione
L'harness è distribuito per diversi agenti. I dettagli completi sul packaging e la checklist
di rilascio sono in [`docs/DISTRIBUTION.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/docs/DISTRIBUTION.md).
**Claude Code** - aggiungi questo repo come plugin marketplace e installa il plugin:```
/plugin marketplace add dmdhrumilmistry/security-harness
/plugin install security-harness
/plugin marketplace add accetta uno qualsiasi tra: un owner/repo di GitHub (come sopra), un URL git completo
(https://github.com/dmdhrumilmistry/security-harness.git), o un percorso locale a un clone
(ad es. /plugin marketplace add ./security-harness dalla directory che contiene il tuo checkout).
Poi esegui /plugin install security-harness e ricarica quando richiesto.
Gemini CLI - un'estensione nativa, con manifest alla radice del repo:```bash gemini extensions install https://github.com/dmdhrumilmistry/security-harness
**opencode, Codex o qualsiasi agente [agentskills.io](https://agentskills.io)** - copia le
skill in una directory di discovery. Codex rileva inoltre `AGENTS.md` autonomamente:```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
Graft viene installato e configurato automaticamente dalla pipeline. Lo Stage 0 esegue npm install -g @nanonets/graft se manca (richiede Node/npm), poi graft init <target> --no-agents --no-global
per registrare il server MCP di Graft e gli hook di freshness per il repository target. Il grafo stesso (<target>/graft/,
auto-gitignored) viene costruito durante la fase di recon. Per pre-installarlo manualmente: npm install -g @nanonets/graft. La build
strutturale di Graft è gratuita e non richiede API key; il passaggio LLM opzionale --deep usa GRAFT_API_KEY /
GRAFT_PROVIDER / GRAFT_MODEL quando impostati.
Anche gli altri tool vengono installati automaticamente dallo Stage 0 quando mancano (tramite qualunque package manager sia presente sulla
macchina - winget/choco/scoop, brew, apt, npm/pip/go - vedi references/tooling-setup.md). Le installazioni vengono
annunciate, preferiscono metodi senza elevazione e non bloccano mai l'esecuzione: tutto ciò che non può essere installato viene semplicemente
marcato come non disponibile e la pipeline esegue il fallback. Lo Stage 0 installa solo ciò che colma un gruppo di capacità mancante:
syft · CVE: uno tra grype
(preferito), trivy, o osv-scannerwkhtmltopdf o pandoc (per PDF/DOCX); altrimenti ottieni report.html (o un PDF generato con headless-Chrome).Tutti sono opzionali - la pipeline degrada in modo controllato verso ricerca nativa + parsing dei manifest se nessuno viene installato.
Invoca il router con una richiesta in linguaggio naturale:``` /sh-router full security review of ./api /sh-router find SQLi and IDOR in src/ /sh-router just map this codebase # recon only
Oppure chiama direttamente la pipeline:```
/sh-security-review . classes:sqli,access-control,ssrf depth:deep
/sh-security-review . stage:report # regenerate reports for the latest run
Ogni fase viene eseguita su un modello adeguato al suo carico cognitivo, così i token vengono spesi dove la qualità della scoperta dipende effettivamente da essi e risparmiati sul lavoro meccanico. Questa è l'impostazione predefinita - non sono necessari argomenti.
| Fase | Modello predefinito |
|---|---|
| recon | sonnet |
| hunt (per classe) | haiku per le classi di pattern (secrets, crypto, open-redirect, csrf) · sonnet per il tracciamento source→sink (sqli, xss, ssrf, injection, path-traversal, xxe, file-upload, auth) · opus per le classi di logica profonda (access-control, race-conditions, deserialization) |
| chain | opus |
| verify | opus (il gate di precisione - mantenuto forte) |
| report | haiku |
Sovrascrivi con l'argomento models: (passato anche attraverso il 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
Stages: `setup, recon, hunt, chain, verify, report`. Models: `opus, sonnet, haiku, inherit`. Per `hunt`,
un modello nudo appiattisce tutti gli hunter su di esso; `hunt.pattern` / `hunt.trace` / `hunt.logic` puntano a un singolo tier.
Altri risparmiatori di token sono integrati: recon genera hunter solo per le classi con una reale superficie d'attacco, gli hunter
interrogano il grafo Graft invece di leggere interi file, e `findings.json`/SARIF sono generati da uno
script deterministico anziché dal modello.
### Output
Tutto finisce sotto `<target>/.security-harness/<run-id>/`:
- `recon.md`, `codebase-map.json` - la mappa (stack, SBOM, CVE, superficie d'attacco).
- `findings.jsonl` → `chains.md` → `verified.jsonl` - lo stato di lavoro (vedi `references/state-files.md`).
- `reports/` - `README.md`, `findings.json`, `results.sarif`, `report.html`, `report.pdf` (+ `report.docx`).
Ogni finding pubblicato porta con sé un payload, un PoC, il verdetto di verifica, gli id CWE/OWASP, il CVSS e una
mitigazione a livello di codice.
## Revisione delle pull request
`sh-pr-review` revisiona una singola pull request anziché un intero codebase, pubblica il
risultato come commenti inline **sulla PR stessa**, e imposta uno stato di commit `security/pr-review`
che la branch protection può far rispettare.
**Eseguilo dalla tua macchina, su qualsiasi PR tu possa leggere.** Installa il plugin e chiedi:```
review https://github.com/acme/api/pull/128
review PR 42
security review this PR
Incolla un link a una PR e revisiona quella PR in quel repository, clonandolo prima in una directory temporanea, perché gli hunter leggono i file e non solo la patch. Nulla viene scritto nel repo su cui stai lavorando.
Passa un numero semplice e viene risolto rispetto al repo in cui ti trovi attualmente, quello
a cui punta git remote. Non passare nulla e prende la PR aperta per il tuo branch corrente.
La Fase 7 stampa i risultati e il verdetto e chiede prima di pubblicare qualsiasi cosa - un rifiuto è un esito normale, e il payload resta su disco perché tu possa pubblicarlo più tardi.
Prima di spendere qualsiasi analisi verifica se puoi effettivamente scrivere sul repo di destinazione, così revisionare il progetto di qualcun altro ti dice in anticipo che la pubblicazione darà 403 invece di scoprirlo dieci minuti dopo.
Tre proprietà lo rendono utilizzabile come merge gate anziché come rumore:
pr_impact
di introduced, aggravated o pre_existing. I primi due bloccano; pre_existing
viene segnalato e non blocca mai. Bloccare un merge per codice che l'autore non ha mai scritto è come
un check obbligatorio viene eliminato, quindi quando un hunter è incerto tra aggravated e
pre_existing, deve scegliere pre_existing.sh-kb-*,
poi sceglie un tier. Il Tier 0 (nessuna modifica rilevante per la sicurezza) non lancia nulla
e imposta comunque lo stato. Il Tier 3 esegue la pipeline completa.| Verdetto | Stato | Quando |
|---|---|---|
| fail | failure | risultato introduced o aggravated pari o superiore a --fail-on (default medium), confidence >= 80 |
| warn | success | nulla di introduced o aggravated; risultati pre-existing segnalati |
| pass | success | nessun risultato, o triage fermato al Tier 0 |
| error | error | la revisione non è potuta giungere a termine |
warn segnala success di proposito: un warning che blocca un merge è un fallimento con
passaggi extra, e i team reagiscono rimuovendo il check. error è tenuto distinto da
failure così un'esecuzione rotta non sembra mai una vulnerabilità che non ha trovato.
L'evento di revisione è sempre COMMENT, mai REQUEST_CHANGES o APPROVE. Lo stato
del commit è il meccanismo di enforcement, ed è quello che legge la branch protection.
Ambito: la skill scrive sulla pull request e sullo stato del commit, e da nessun'altra parte. Non apre issue e non crea nulla in alcun tracker esterno.
Una PR viene revisionata una volta per push, quindi la seconda revisione deve essere più economica della prima o lo strumento diventa qualcosa che le persone disattivano.
La deduplicazione avviene prima della spesa, non prima della pubblicazione. I fingerprint già presenti sulla PR vengono letti nella Fase 1 e passati agli hunter e al verifier. Trovare un duplicato alla fine significherebbe che il modello più costoso della pipeline aveva già ri-confermato una conclusione che era scritta sulla PR per tutto il tempo. Questo non richiede cache: lo stato vive nella PR, quindi funziona su una macchina fredda e in CI.
Una cache locale rende incrementale il resto. sh-review-cache memorizza gli hash dei file, i risultati e i verdetti
di ogni esecuzione nella directory cache del tuo OS (mai nel repo, poiché una
revisione cross-repo viene eseguita in un clone temporaneo che viene eliminato). La revisione successiva ri-caccia solo
i file il cui contenuto è effettivamente cambiato, riutilizza i verdetti per i risultati invariati e
riutilizza la mappa di recon se nulla di ciò che copre si è spostato.
Un merge dal branch base non costa nulla. Fare il merge di main in un branch di PR cambia l'head
SHA e nulla di ciò che l'autore ha scritto, ma uno stato del commit è ancorato a uno SHA, quindi il check
obbligatorio scompare silenziosamente dal nuovo head. Quando i file della PR sono byte-identici
e il delta della base non tocca nulla da cui dipendono i risultati, il verdetto precedente viene
ri-apposto sul nuovo SHA senza che venga lanciato alcun agente. Quest'ultima condizione è ciò che
lo rende sicuro: un merge dalla base che elimina un sanitizer lascia ogni file della PR invariato mentre
trasforma una riga sicura in una sfruttabile.
L'invalidazione è deliberatamente conservativa, perché una voce obsoleta in uno strumento di sicurezza non
lo rende lento, lo rende sbagliato. La chiave della cache calcola l'hash di ogni knowledge
base sh-kb-*, quindi un aggiornamento della KB invalida ogni risultato in cache - un "clean" in cache non deve mai
sopprimere il risultato che quell'aggiornamento era stato scritto per catturare. Anche l'identità del modello, la versione della skill, il contenuto
dei file e un TTL di 7 giorni invalidano tutto, e un modello non specificato è trattato come un miss.
--no-cache la disabilita, --refresh-cache ri-baselina, e run.md registra per ogni fase
cosa è stato lanciato, riutilizzato e saltato, così una cache che smette silenziosamente di fare hit è visibile
anziché presunta.
La revisione e lo stato del commit vengono pubblicati per impostazione predefinita. Una revisione che è stata calcolata e
mai consegnata non ha aiutato nessuno. --confirm ripristina un prompt prima della pubblicazione, --dry-run
non invia nulla, --no-status pubblica la revisione ma lascia in pace lo stato del commit.
La pubblicazione passa attraverso scripts/sh-pr-post.py anziché chiamate API costruite a mano, perché
è un'operazione multi-step con una coda obbligatoria: revisione, poi stato, poi ricevute, con
un 422 recuperato spostando il commento anziché spostando un numero di riga. Lo script
non esce mai lasciando lo stato a pending - se la revisione non può essere pubblicata imposta comunque
error, dicendo che il tooling ha fallito anziché accusare la PR.
I commenti inline sono riservati ai risultati di severità media o superiore con confidence >= 80. I risultati di bassa severità vanno nella sezione del corpo compressa, quindi un risultato a bassa priorità che compare con zero commenti inline è la policy che funziona, non un fallimento.
Ogni esecuzione registra quanto è costata, così "la cache sta funzionando" e "le revisioni sono diventate più lente" smettono di essere questioni di opinione.```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
Due file JSONL append-only - `runs.jsonl` (repo, PR, tier, verdetto, totali, i flag che hai
passato) e `events.jsonl` (una riga per fase o agente: modello, token, durata, esito,
se è stato riutilizzato dalla cache). JSONL così una run andata in crash lascia comunque righe valide sopra
il crash.
| Piattaforma | Metriche | Cache |
|---|---|---|
| **Linux / BSD** | `$XDG_DATA_HOME/security-harness/metrics`<br>default `~/.local/share/security-harness/metrics` | `$XDG_CACHE_HOME/security-harness`<br>default `~/.cache/security-harness` |
| macOS | `~/Library/Application Support/security-harness/metrics` | `~/Library/Caches/security-harness` |
| Windows | `%LOCALAPPDATA%\security-harness\metrics` | `%LOCALAPPDATA%\security-harness\cache` |
Linux segue la specifica XDG Base Directory, quindi entrambi rispettano `XDG_DATA_HOME` e
`XDG_CACHE_HOME` quando impostate e ricadono su `~/.local/share` e `~/.cache` quando non lo sono.
Sovrascrivi l'una o l'altra direttamente con `SH_METRICS_DIR` e `SH_REVIEW_CACHE_DIR`.
**Su `python` vs `python3`:** la maggior parte delle distribuzioni Linux fornisce `python3` e non ha affatto
`python`, quindi gli esempi qui usano `python3`. Gli script inclusi portano uno
shebang `#!/usr/bin/env python3` e sono eseguibili, quindi `./scripts/sh-metrics.py report`
funziona direttamente su Linux e macOS. La skill risolve
`PY="$(command -v python3 || command -v python)"` una volta per run, il che copre tutte e tre le
piattaforme incluso Git Bash su Windows.
**Strettamente locale.** Nessuno dei due script contiene codice di rete o endpoint di reporting.
Qualsiasi cosa a forma di token viene redatta prima di essere scritta, perché i file locali finiscono incollati
nelle issue.
### Esecuzione non presidiata
Opzionale, e una decisione separata dall'uso della skill. Eseguila a mano sulle tue PR
per un po' prima, così sai cosa dice del tuo codebase prima che lo dica
davanti al tuo team.
Quando sei pronto, "Enforcing the check on a repository" in
[`references/pr-review-mapping.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/plugins/security-harness/references/pr-review-mapping.md)
ha un workflow copia-incolla per **il tuo** repo, più il fail-safe che impedisce a un job morto
di lasciare un check richiesto bloccato su `pending`.
La soglia resta al default `medium`. I finding preesistenti non bloccano mai un merge,
quindi un codebase non scansionato non produce un muro di rosso al giorno uno - solo ciò che una PR
introduce o aggrava effettivamente può farlo fallire.
## Come funziona
1. **Setup** - sonda gli strumenti disponibili, definisci lo scope, crea la directory di run.
2. **Recon** (`sh-recon`) - costruisci il grafo Graft; rileva stack/versioni; SBOM + CVE; enumera entry
point, trust boundary e sink pericolosi.
3. **Hunt** (`sh-hunter` ×N, in parallelo) - un hunter per ogni classe rilevante carica la sua knowledge base `sh-kb-*`,
traccia l'input dell'attaccante dalla source al sink e registra i candidati. Un **attempts ledger** condiviso impedisce
agli agenti di ripetere le sonde l'uno dell'altro.
4. **Chain** (`sh-chainer`) - compone i finding in percorsi di attacco a severità più alta.
5. **Verify** (`sh-verifier`) - confuta prima, poi conferma l'exploitabilità dalle evidenze, costruisci PoC, assegna
CVSS e taglia i falsi positivi.
6. **Report** (`sh-reporter`) - produci i deliverable.
I subagent non condividono nulla tranne i file; il contratto è in `plugins/security-harness/references/state-files.md`.
## Estendere
Aggiungi una nuova classe di vulnerabilità creando `skills/sh-kb-<class>/SKILL.md` seguendo il template condiviso
(When to hunt · Sources & sinks · Detection recipe · Payloads/PoC · False-positive filters · CWE/OWASP ·
Chaining hints · Mitigation), poi aggiungi il suo slug all'enum `class` in `references/finding-schema.json`
e alla routing table in `skills/sh-router/SKILL.md`.
## Aggiornamenti automatici della knowledge-base
Una GitHub Action pianificata (`.github/workflows/update-knowledge-base.yml`) mantiene fresche le knowledge
base `sh-kb-*`. **Ogni due giorni** (e su `workflow_dispatch` manuale), esegue un agente per distillare nuova,
autorevole ricerca di sicurezza pubblica - OWASP, PortSwigger Research, CWE/CAPEC, NIST, MDN, repo GitHub curati
e disclosure pubbliche di HackerOne - in piccoli miglioramenti ben documentati. Un **secondo agente revisore
avversariale** scansiona poi il diff risultante per contenuti malevoli/iniettati, e la PR viene
**auto-mergiata solo se quel revisore approva**.
### Due workflow, tre job
La creazione della PR è deliberatamente separata dalla review e dal merge, così la cosa che scrive
il diff non è mai la cosa che decide di spedirlo.
**Stage 1 - [`update-knowledge-base.yml`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/workflows/update-knowledge-base.yml)**
(pianificato o manuale). Un job, `create-pr`:
1. **Generate** - l'agente modifica la KB da fonti in allowlist. Nessun commit, nessun push.
2. **Open PR** - uno step deterministico apre (o aggiorna) una PR sul branch `automated/kb-update`,
etichettata `awaiting-review`.
3. **Hand off** - su una creazione di PR riuscita, dispatcha lo stage 2 con il numero della PR.
**Stage 2 - [`kb-review-and-merge.yml`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/workflows/kb-review-and-merge.yml)**
(dispatchato dallo stage 1, o eseguito a mano contro qualsiasi PR automatizzata). Due job:
- **`review`** - una run di un agente *separato* ispeziona il diff **avversarialmente** per
artefatti di prompt-injection, modifiche fuori scope, secret/exfil, PII, exploit
weaponizzati, sourcing fuori allowlist o violazioni dello stile del progetto. Non ha **né web né
shell**, e **fallisce in modo chiuso**: qualsiasi cosa sospetta, qualsiasi incertezza o un file di
verdetto mancante → REJECT. Il verdetto viene pubblicato come commento sulla PR e guida la label.
- **`merge`** - viene eseguito **solo** su `APPROVE`, e mergia la PR. Un `REJECT` lo salta e
il job `blocked` riporta il perché.
> **Perché un dispatch invece di un trigger `pull_request`:** una PR aperta da `GITHUB_TOKEN`
> non attiva i workflow `pull_request`. `workflow_dispatch` è uno dei due eventi
> esenti da quella guardia di ricorsione, quindi lo stage 1 può fare hand off in modo affidabile.
**Auto-merge significa che un agente che approva fa atterrare codice in `main`.** I controlli su questo:
- Il job di merge rifiuta qualsiasi PR chiusa, da un fork, o il cui head branch è
fuori da `automated/*` (`ALLOWED_HEAD_PREFIX` nel workflow).
- Preferisce l'auto-merge di GitHub stesso, quindi **la branch protection si applica comunque**. Con una regola
su `main` che richiede una review approvante, la PR si accoda e aspetta un umano invece di
mergiare. Ricade su un merge immediato solo su repo dove l'auto-merge è disattivato.
- Imposta l'input `auto_merge` a `false` su una run manuale per fare review senza mergiare.
- Il prompt del revisore dice all'agente che il suo verdetto è vincolante, non consultivo.
> Richiede l'impostazione del repo **"Allow GitHub Actions to create and approve pull requests"** (Settings →
> Actions → General → Workflow permissions) così il workflow può aprire la PR. Se vuoi un umano nel
> loop nonostante l'auto-merge, proteggi `main` con una regola di branch-protection che richiede una pull request e
> almeno una review approvante - il percorso di auto-merge la rispetta.
### Agenti pluggable
Entrambi gli stage girano attraverso [`.github/actions/ai-agent`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/actions/ai-agent/action.yml),
una composite action che dispatcha verso l'agente che configuri. Claude Code, OpenAI
Codex, Gemini CLI e una via di fuga per qualsiasi altro:
| `agent` | Esegue | Credenziale |
|---|---|---|
| `claude` (default) | `anthropics/claude-code-action@v1` | `CLAUDE_CODE_OAUTH_TOKEN` o `ANTHROPIC_API_KEY` |
| `codex` | `codex exec --full-auto` | `OPENAI_API_KEY` |
| `gemini` | `gemini --yolo --prompt` | `GEMINI_API_KEY` |
| `custom` | il tuo `KB_AGENT_INSTALL` / `KB_AGENT_COMMAND` | qualunque cosa gli serva |
Scegli per run dagli input di `workflow_dispatch`, o imposta variabili del repo per cambiare il
default: `KB_AGENT` e `KB_MODEL` per il generatore, `KB_REVIEW_AGENT` e
`KB_REVIEW_MODEL` per il revisore. Eseguire il generatore e il revisore su **agenti
diversi** è un passo di hardening significativo: un'injection tarata per un modello è meno probabile
che atterri su un secondo, indipendente.
Per `agent: custom`, imposta `KB_AGENT_COMMAND` a un comando shell. Il prompt viene scritto nel
file indicato da `$AGENT_PROMPT_FILE`, e `$AGENT_MODEL` porta l'input del modello.
Difese contro il prompt-injection, dato che il generatore legge il web aperto:
- **Allowlist di domini.** `WebFetch` è limitato ai domini fidati in
`.github/kb-update/trusted-sources.md` (rispecchiati nel `--allowedTools` del workflow). `WebSearch` può
scoprire URL, ma solo i domini in allowlist possono effettivamente essere fetchati.
- **Il contenuto è dato, non comando.** Il prompt del task (`.github/kb-update/prompt.md`) istruisce Claude a
trattare ogni byte fetchato come materiale di riferimento non fidato e a ignorare qualsiasi istruzione incorporata in una
pagina - i corpi dei report HackerOne (generati dagli utenti) sono segnalati come il tier a rischio più alto.
- **Niente shell, niente push sul generatore; il revisore è il gate.** Il generatore può solo modificare file.
Il revisore indipendente (`.github/kb-update/review-prompt.md`) è ciò che sta tra il contenuto fetchato
e `main` - nulla viene mergiato senza la sua approvazione esplicita.
- **Agenti diversi per generatore e revisore.** Opzionale, e la versione più forte del gate: imposta
`KB_AGENT` e `KB_REVIEW_AGENT` su due motori diversi.
**Setup:**
- Aggiungi la credenziale per l'agente che usi (Settings → Secrets and variables → Actions):
**`CLAUDE_CODE_OAUTH_TOKEN`** (default), `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` o `GEMINI_API_KEY`.
Il token OAuth si autentica contro **i limiti di utilizzo del tuo abbonamento Claude** invece che con una API key a
consumo - generalo localmente con `claude setup-token` (richiede un abbonamento Claude Pro/Max attivo)
e incolla il risultato.
- Abilita **"Allow GitHub Actions to create and approve pull requests"** (Settings → Actions → General →
Workflow permissions) così il workflow può aprire la sua PR. Consigliato: aggiungi una regola di branch-protection su `main`
che richiede una PR e una review approvante, così nessuna modifica automatizzata può atterrare senza un umano anche con
l'auto-merge attivo.
- Per cambiare quali fonti sono consentite, modifica l'allowlist in `trusted-sources.md` **e** le corrispondenti
voci `WebFetch(domain:...)` nel workflow - mantieni le due sincronizzate.
Ogni run registra cosa ha fatto in `.github/kb-update/last-run-summary.md`.
## Roadmap
- ~~Wiring del mirror Codex / Cursor.~~
✅ Rilasciato: `AGENTS.md`, un'estensione Gemini CLI e `scripts/sync-agent-skills.py`
per `.agents/skills` e opencode. Vedi [`docs/DISTRIBUTION.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/docs/DISTRIBUTION.md).
- ~~Augmentazione opzionale live-fetch delle knowledge base (PortSwigger/OWASP/CWE) sopra i riferimenti curati.~~
✅ Rilasciato come l'updater pianificato della knowledge-base sopra.
- Bridge DAST opzionale per la conferma a runtime dei finding `needs-runtime`.
## Licenza
MIT