Arnés de revisión estática de seguridad de aplicaciones multiagente para agentes de codificación de IA: mapea bases de código, caza clases de vulnerabilidades, encadena y verifica hallazgos, y reporta a SARIF, JSON y PDF.
Un arnés de revisión de seguridad de aplicaciones multiagente para Claude Code (y, más adelante, otros agentes de IA). Una habilidad de enrutador despacha a un pipeline completo de seguridad ofensiva que mapea una base de código, caza vulnerabilidades con una base de conocimiento por clase, encadena hallazgos en escaladas, verifica el impacto real y reporta a README / JSON / SARIF / doc / PDF.
Alcance: este arnés realiza análisis estático (revisión de código fuente, trazado de flujo de datos, construcción de PoC/payload) sobre código que posees o estás autorizado a probar. No ataca sistemas de terceros en vivo.
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)
### Clases de vulnerabilidad cubiertas (las habilidades `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. Los CVE de dependencias/SBOM son gestionados por la etapa de recon.
## Instalación
El harness se distribuye para varios agentes. Los detalles completos de empaquetado y la lista de verificación de la versión están en [`docs/DISTRIBUTION.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/docs/DISTRIBUTION.md).
**Claude Code** - añade este repositorio como un marketplace de plugins e instala el plugin:```
/plugin marketplace add dmdhrumilmistry/security-harness
/plugin install security-harness
/plugin marketplace add acepta cualquiera de los siguientes: un owner/repo de GitHub (como arriba), una URL de git completa
(https://github.com/dmdhrumilmistry/security-harness.git), o una ruta local a un clon
(p. ej. /plugin marketplace add ./security-harness desde el directorio que contiene tu copia local).
Luego ejecuta /plugin install security-harness y recarga cuando se te solicite.
Gemini CLI - una extensión nativa, con el manifiesto en la raíz del repositorio:```bash gemini extensions install https://github.com/dmdhrumilmistry/security-harness
**opencode, Codex o cualquier agente de [agentskills.io](https://agentskills.io)** - copia las
skills en un directorio de descubrimiento. Codex además detecta `AGENTS.md` por su cuenta:```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 se instala y configura automáticamente mediante el pipeline. La Etapa 0 ejecuta npm install -g @nanonets/graft si falta (requiere Node/npm), luego graft init <target> --no-agents --no-global
para registrar el servidor MCP de Graft y los hooks de frescura para el repositorio objetivo. El grafo en sí (<target>/graft/,
auto-gitignored) se construye durante el reconocimiento. Para preinstalar manualmente: npm install -g @nanonets/graft. La construcción
estructural de Graft es gratuita y no necesita clave de API; la pasada opcional --deep de LLM usa GRAFT_API_KEY /
GRAFT_PROVIDER / GRAFT_MODEL cuando están configuradas.
Las otras herramientas también se instalan automáticamente mediante la Etapa 0 cuando faltan (a través del gestor de paquetes que esté en la
máquina - winget/choco/scoop, brew, apt, npm/pip/go - consulta references/tooling-setup.md). Las instalaciones se
anuncian, prefieren métodos sin elevación y nunca bloquean la ejecución: cualquier cosa que no se pueda instalar simplemente se
marca como no disponible y el pipeline recurre a alternativas. La Etapa 0 solo instala lo que cubre un grupo de capacidades faltante:
syft · CVEs: uno de grype
(preferido), trivy, o osv-scannerwkhtmltopdf o pandoc (para PDF/DOCX); de lo contrario obtienes report.html (o un PDF de Chrome headless).Todas son opcionales - el pipeline se degrada de forma elegante a búsqueda nativa + análisis de manifiestos si ninguna se instala.
Invoca el router con una solicitud en lenguaje natural:``` /sh-router full security review of ./api /sh-router find SQLi and IDOR in src/ /sh-router just map this codebase # recon only
O llama al pipeline directamente:```
/sh-security-review . classes:sqli,access-control,ssrf depth:deep
/sh-security-review . stage:report # regenerate reports for the latest run
Cada etapa se ejecuta en un modelo ajustado a su carga cognitiva, de modo que los tokens se gastan donde la calidad del descubrimiento realmente depende de ellos y se ahorran en el trabajo mecánico. Este es el comportamiento predeterminado: no se necesitan argumentos.
| Etapa | Modelo predeterminado |
|---|---|
| recon | sonnet |
| hunt (por clase) | haiku para clases de patrones (secrets, crypto, open-redirect, csrf) · sonnet para el trazado source→sink (sqli, xss, ssrf, injection, path-traversal, xxe, file-upload, auth) · opus para clases de lógica profunda (access-control, race-conditions, deserialization) |
| chain | opus |
| verify | opus (la puerta de precisión - se mantiene fuerte) |
| report | haiku |
Se puede sobrescribir con el argumento models: (que también se pasa a través del 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
Etapas: `setup, recon, hunt, chain, verify, report`. Modelos: `opus, sonnet, haiku, inherit`. Para `hunt`,
un modelo sin calificador aplana todos los hunters a ese modelo; `hunt.pattern` / `hunt.trace` / `hunt.logic` apuntan a un solo nivel.
Otros ahorradores de tokens están integrados: recon solo genera hunters para clases con superficie de ataque real, los hunters
consultan el grafo Graft en lugar de leer archivos completos, y `findings.json`/SARIF son generados por un
script determinista en lugar del modelo.
### Salida
Todo queda bajo `<target>/.security-harness/<run-id>/`:
- `recon.md`, `codebase-map.json` - el mapa (stack, SBOM, CVEs, superficie de ataque).
- `findings.jsonl` → `chains.md` → `verified.jsonl` - el estado de trabajo (ver `references/state-files.md`).
- `reports/` - `README.md`, `findings.json`, `results.sarif`, `report.html`, `report.pdf` (+ `report.docx`).
Cada hallazgo publicado incluye un payload, un PoC, el veredicto de verificación, ids CWE/OWASP, CVSS y una
mitigación a nivel de código.
## Revisión de pull request
`sh-pr-review` revisa un único pull request en lugar de todo un código base, publica el
resultado como comentarios en línea **en el propio PR**, y establece un estado de commit `security/pr-review`
que la protección de rama puede hacer cumplir.
**Ejecútalo desde tu propia máquina, en cualquier PR que puedas leer.** Instala el plugin y pregunta:```
review https://github.com/acme/api/pull/128
review PR 42
security review this PR
Pega un enlace de PR y revisa ese PR en ese repositorio, clonándolo primero en un directorio temporal, porque los hunters leen archivos y no solo el parche. No se escribe nada en el repositorio en el que estás trabajando.
Pasa un número sin más y se resuelve contra el repositorio en el que estás actualmente, el que apunta git remote. No pases nada y toma el PR abierto de tu rama actual.
La Fase 7 imprime los hallazgos y el veredicto y pregunta antes de publicar cualquier cosa - un rechazo es un resultado normal, y el payload permanece en disco para que lo publiques más tarde.
Antes de gastar cualquier análisis comprueba si realmente puedes escribir en el repositorio objetivo, así que revisar el proyecto de otra persona te dice de antemano que publicar dará 403 en lugar de descubrirlo diez minutos después.
Tres propiedades lo hacen utilizable como puerta de merge en lugar de ruido:
pr_impact de introduced, aggravated o pre_existing. Los dos primeros bloquean; pre_existing se reporta y nunca bloquea. Bloquear un merge por código que el autor nunca escribió es como se acaba eliminando una comprobación requerida, así que cuando un hunter duda entre aggravated y pre_existing, debe elegir pre_existing.sh-kb-*, y luego elige un nivel. El Nivel 0 (ningún cambio relevante para la seguridad) no lanza nada en absoluto y aun así establece el estado. El Nivel 3 ejecuta el pipeline completo.| Veredicto | Estado | Cuándo |
|---|---|---|
| fail | failure | hallazgo introduced o aggravated igual o superior a --fail-on (por defecto medium), confianza >= 80 |
| warn | success | nada introduced o aggravated; hallazgos pre-existing reportados |
| pass | success | sin hallazgos, o el triaje se detuvo en el Nivel 0 |
| error | error | la revisión no pudo completarse |
warn reporta success a propósito: una advertencia que bloquea un merge es un fallo con pasos extra, y los equipos responden eliminando la comprobación. error se mantiene distinto de failure para que una ejecución rota nunca parezca una vulnerabilidad que no encontró.
El evento de revisión es siempre COMMENT, nunca REQUEST_CHANGES ni APPROVE. El estado del commit es el mecanismo de aplicación, y es el único que lee la protección de rama.
Alcance: la skill escribe en el pull request y en el estado del commit, y en ningún otro sitio. No abre issues ni crea nada en ningún tracker externo.
Un PR se revisa una vez por push, así que la segunda revisión tiene que ser más barata que la primera o la herramienta se convierte en algo que la gente desactiva.
La deduplicación ocurre antes del gasto, no antes de la publicación. Las huellas que ya están en el PR se leen en la Fase 1 y se entregan a los hunters y al verificador. Encontrar un duplicado al final significaría que el modelo más caro del pipeline ya habría reconfirmado una conclusión que estuvo escrita en el PR todo el tiempo. Esto no necesita caché: el estado vive en el PR, así que funciona en una máquina en frío y en CI.
Una caché local hace que el resto sea incremental. sh-review-cache almacena los hashes de archivos, hallazgos y veredictos de cada ejecución bajo el directorio de caché de tu SO (nunca en el repositorio, ya que una revisión entre repositorios se ejecuta en un clon temporal que se elimina). La siguiente revisión solo vuelve a cazar los archivos cuyo contenido cambió realmente, reutiliza veredictos para hallazgos que no han cambiado, y reutiliza el mapa de reconocimiento si nada de lo que cubre se ha movido.
Un merge de la rama base no cuesta nada. Fusionar main en una rama de PR cambia el SHA de head y nada de lo que escribió el autor, pero un estado de commit está fijado a un SHA, así que la comprobación requerida desaparece silenciosamente del nuevo head. Cuando los archivos propios del PR son byte-idénticos y el delta de la base no toca nada de lo que dependen los hallazgos, el veredicto anterior se re-sella sobre el nuevo SHA sin lanzar ningún agente en absoluto. Esa última condición es lo que lo hace seguro: un merge de la base que elimina un sanitizer deja todos los archivos del PR sin cambios mientras convierte una línea segura en una explotable.
La invalidación es deliberadamente conservadora, porque una entrada obsoleta en una herramienta de seguridad no la hace lenta, la hace incorrecta. La clave de caché hashea cada base de conocimiento sh-kb-*, así que una actualización de la KB invalida cada hallazgo cacheado - un "clean" cacheado nunca debe suprimir el hallazgo que esa actualización fue escrita para capturar. La identidad del modelo, la versión de la skill, el contenido de los archivos y un TTL de 7 días también invalidan, y un modelo no especificado se trata como un fallo de caché.
--no-cache la desactiva, --refresh-cache re-baseliza, y run.md registra por fase qué se lanzó, se reutilizó y se omitió, así que una caché que deja de acertar silenciosamente es visible en lugar de asumida.
La revisión y el estado del commit se publican por defecto. Una revisión que se calculó y nunca se entregó no ayudó a nadie. --confirm restaura un prompt antes de publicar, --dry-run no envía nada, --no-status publica la revisión pero deja el estado del commit en paz.
La publicación pasa por scripts/sh-pr-post.py en lugar de llamadas a la API construidas a mano, porque es una operación de varios pasos con una cola obligatoria: revisión, luego estado, luego recibos, con un 422 recuperado moviendo el comentario en lugar de desplazar un número de línea. El script nunca sale dejando el estado en pending - si la revisión no se puede publicar, aun así establece error, diciendo que el tooling falló en lugar de acusar al PR.
Los comentarios inline están reservados para hallazgos de medium o superior con confianza >= 80. Los hallazgos de baja severidad van en la sección de cuerpo colapsada, así que un hallazgo de baja prioridad que aparece con cero comentarios inline es la política funcionando, no un fallo.
Cada ejecución registra lo que costó, para que "la caché está funcionando" y "las revisiones se volvieron más lentas" dejen de ser cuestiones de opinión.```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
Dos archivos JSONL de solo adición: `runs.jsonl` (repo, PR, nivel, veredicto, totales, los flags que
pasaste) y `events.jsonl` (una línea por fase o agente: modelo, tokens, duración, resultado,
si se reutilizó desde caché). JSONL para que una ejecución fallida aún deje líneas válidas por encima
del fallo.
| Plataforma | Métricas | Caché |
|---|---|---|
| **Linux / BSD** | `$XDG_DATA_HOME/security-harness/metrics`<br>por defecto `~/.local/share/security-harness/metrics` | `$XDG_CACHE_HOME/security-harness`<br>por defecto `~/.cache/security-harness` |
| macOS | `~/Library/Application Support/security-harness/metrics` | `~/Library/Caches/security-harness` |
| Windows | `%LOCALAPPDATA%\security-harness\metrics` | `%LOCALAPPDATA%\security-harness\cache` |
Linux sigue la especificación XDG Base Directory, por lo que ambas respetan `XDG_DATA_HOME` y
`XDG_CACHE_HOME` cuando están definidas y recurren a `~/.local/share` y `~/.cache` cuando no lo están.
Anula cualquiera de las dos directamente con `SH_METRICS_DIR` y `SH_REVIEW_CACHE_DIR`.
**Sobre `python` vs `python3`:** la mayoría de las distribuciones de Linux incluyen `python3` y no tienen
`python` en absoluto, por lo que los ejemplos aquí usan `python3`. Los scripts incluidos llevan un
shebang `#!/usr/bin/env python3` y son ejecutables, así que `./scripts/sh-metrics.py report`
funciona directamente en Linux y macOS. La skill resuelve
`PY="$(command -v python3 || command -v python)"` una vez por ejecución, lo que cubre las tres
plataformas, incluido Git Bash en Windows.
**Estrictamente local.** Ninguno de los scripts contiene código de red ni endpoint de reporte.
Todo lo que tenga forma de token se redacta antes de escribirse, porque los archivos locales se pegan
en issues.
### Ejecutarlo sin supervisión
Opcional, y una decisión separada de usar la skill. Ejecútalo a mano en tus propios PRs
durante un tiempo primero, para que sepas qué dice sobre tu base de código antes de que lo diga
delante de tu equipo.
Cuando estés listo, "Enforcing the check on a repository" en
[`references/pr-review-mapping.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/plugins/security-harness/references/pr-review-mapping.md)
tiene un flujo de trabajo listo para copiar y pegar para **tu** repo, además del fail-safe que evita que un job muerto
deje una comprobación requerida atascada en `pending`.
El umbral se mantiene en el valor predeterminado `medium`. Los hallazgos preexistentes nunca bloquean un merge,
así que una base de código sin escanear no produce un muro de rojo el primer día: solo lo que un PR
realmente introduce o agrava puede hacerlo fallar.
## Cómo funciona
1. **Setup** - sondear las herramientas disponibles, definir el alcance, crear el directorio de ejecución.
2. **Recon** (`sh-recon`) - construir el grafo Graft; detectar stack/versiones; SBOM + CVEs; enumerar puntos de entrada,
límites de confianza y sinks peligrosos.
3. **Hunt** (`sh-hunter` ×N, en paralelo) - un hunter por clase relevante carga su base de conocimiento `sh-kb-*`,
rastrea la entrada del atacante desde el source hasta el sink y registra candidatos. Un **ledger de intentos** compartido evita
que los agentes repitan las sondas de los demás.
4. **Chain** (`sh-chainer`) - componer los hallazgos en rutas de ataque de mayor severidad.
5. **Verify** (`sh-verifier`) - refutar primero, luego confirmar la explotabilidad a partir de la evidencia, construir PoCs, asignar
CVSS y descartar falsos positivos.
6. **Report** (`sh-reporter`) - producir los entregables.
Los subagentes no comparten nada más que archivos; el contrato está en `plugins/security-harness/references/state-files.md`.
## Extender
Añade una nueva clase de vulnerabilidad creando `skills/sh-kb-<class>/SKILL.md` siguiendo la plantilla compartida
(Cuándo cazar · Sources & sinks · Receta de detección · Payloads/PoC · Filtros de falsos positivos · CWE/OWASP ·
Sugerencias de encadenamiento · Mitigación), luego añade su slug al enum `class` en `references/finding-schema.json`
y a la tabla de enrutamiento en `skills/sh-router/SKILL.md`.
## Actualizaciones automatizadas de la base de conocimiento
Una GitHub Action programada (`.github/workflows/update-knowledge-base.yml`) mantiene frescas las bases de conocimiento
`sh-kb-*`. **Cada dos días** (y con `workflow_dispatch` manual), ejecuta un agente para destilar nueva
investigación de seguridad pública y reputada - OWASP, PortSwigger Research, CWE/CAPEC, NIST, MDN, repos de GitHub
curados y divulgaciones públicas de HackerOne - en pequeñas mejoras bien fundamentadas. Un **segundo agente revisor
adversarial** luego escanea el diff resultante en busca de contenido malicioso/inyectado, y el PR se
**auto-fusiona solo si ese revisor lo aprueba**.
### Dos workflows, tres jobs
La creación del PR está deliberadamente separada de la revisión y el merge, para que lo que escribe
el diff nunca sea lo que decide publicarlo.
**Etapa 1 - [`update-knowledge-base.yml`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/workflows/update-knowledge-base.yml)**
(programada o manual). Un job, `create-pr`:
1. **Generar** - el agente edita la KB desde fuentes permitidas. Sin commit, sin push.
2. **Abrir PR** - un paso determinista abre (o actualiza) un PR en la rama `automated/kb-update`,
etiquetado como `awaiting-review`.
3. **Traspaso** - tras una creación exitosa del PR, despacha la etapa 2 con el número del PR.
**Etapa 2 - [`kb-review-and-merge.yml`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/workflows/kb-review-and-merge.yml)**
(despachada por la etapa 1, o ejecutada a mano contra cualquier PR automatizado). Dos jobs:
- **`review`** - una ejecución de agente *separada* inspecciona el diff **de forma adversarial** en busca de
artefactos de prompt-injection, ediciones fuera de alcance, secretos/exfiltración, PII, exploits
weaponizados, fuentes fuera de la allowlist o violaciones del estilo del proyecto. **No tiene web ni
shell**, y **falla en cerrado**: cualquier cosa sospechosa, cualquier incertidumbre o un archivo de
veredicto ausente → REJECT. El veredicto se publica como comentario en el PR e impulsa la etiqueta.
- **`merge`** - se ejecuta **solo** con `APPROVE`, y fusiona el PR. Un `REJECT` lo omite y
el job `blocked` informa por qué.
> **Por qué un dispatch en lugar de un trigger `pull_request`:** un PR abierto por `GITHUB_TOKEN`
> no dispara workflows `pull_request`. `workflow_dispatch` es uno de los dos eventos
> exentos de esa protección de recursión, por lo que la etapa 1 puede hacer el traspaso de forma fiable.
**Auto-merge significa que un agente aprobador aterriza código en `main`.** Los controles sobre eso:
- El job de merge rechaza cualquier PR que esté cerrado, provenga de un fork o cuya rama head esté
fuera de `automated/*` (`ALLOWED_HEAD_PREFIX` en el workflow).
- Prefiere el auto-merge propio de GitHub, por lo que **la protección de rama sigue aplicándose**. Con una regla
en `main` que requiera una revisión aprobatoria, el PR se pone en cola y espera a un humano en lugar de
fusionarse. Solo recurre a un merge inmediato en repos donde el auto-merge está desactivado.
- Establece la entrada `auto_merge` en `false` en una ejecución manual para revisar sin fusionar.
- El prompt del revisor le dice al agente que su veredicto es vinculante, no consultivo.
> Requiere la configuración del repo **"Allow GitHub Actions to create and approve pull requests"** (Settings →
> Actions → General → Workflow permissions) para que el workflow pueda abrir el PR. Si quieres un humano en el
> bucle a pesar del auto-merge, protege `main` con una regla de protección de rama que requiera un pull request y al
> menos una revisión aprobatoria - la ruta de auto-merge la respeta.
### Agentes conectables
Ambas etapas se ejecutan a través de [`.github/actions/ai-agent`](https://github.com/dmdhrumilmistry/security-harness/blob/main/.github/actions/ai-agent/action.yml),
una acción compuesta que despacha al agente que configures. Claude Code, OpenAI
Codex, Gemini CLI y una vía de escape para cualquier otra cosa:
| `agent` | Ejecuta | Credencial |
|---|---|---|
| `claude` (por defecto) | `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` | tu `KB_AGENT_INSTALL` / `KB_AGENT_COMMAND` | lo que necesite |
Elige por ejecución desde las entradas de `workflow_dispatch`, o establece variables del repo para cambiar el
valor predeterminado: `KB_AGENT` y `KB_MODEL` para el generador, `KB_REVIEW_AGENT` y
`KB_REVIEW_MODEL` para el revisor. Ejecutar el generador y el revisor en **agentes
distintos** es un paso de endurecimiento significativo: una inyección ajustada para un modelo es menos probable
que aterrice en un segundo, independiente.
Para `agent: custom`, establece `KB_AGENT_COMMAND` en un comando de shell. El prompt se escribe en
el archivo nombrado por `$AGENT_PROMPT_FILE`, y `$AGENT_MODEL` lleva la entrada del modelo.
Defensas contra prompt-injection, ya que el generador lee la web abierta:
- **Allowlist de dominios.** `WebFetch` está restringido a los dominios de confianza en
`.github/kb-update/trusted-sources.md` (reflejados en `--allowedTools` del workflow). `WebSearch` puede
descubrir URLs, pero solo los dominios en la allowlist pueden realmente ser obtenidos.
- **El contenido son datos, no comandos.** El prompt de la tarea (`.github/kb-update/prompt.md`) instruye a Claude a
tratar cada byte obtenido como material de referencia no confiable y a ignorar cualquier instrucción incrustada en una
página - los cuerpos de informes de HackerOne (generados por usuarios) se marcan como el nivel de mayor riesgo.
- **Sin shell, sin push en el generador; el revisor es la puerta.** El generador solo puede editar archivos.
El revisor independiente (`.github/kb-update/review-prompt.md`) es lo que se interpone entre el contenido obtenido
y `main` - nada se fusiona sin su aprobación explícita.
- **Agentes distintos para el generador y el revisor.** Opcional, y la versión más fuerte de la puerta: establece
`KB_AGENT` y `KB_REVIEW_AGENT` en dos motores diferentes.
**Configuración:**
- Añade la credencial para el agente que uses (Settings → Secrets and variables → Actions):
**`CLAUDE_CODE_OAUTH_TOKEN`** (por defecto), `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` o `GEMINI_API_KEY`.
El token OAuth se autentica contra **los límites de uso de tu suscripción de Claude** en lugar de una API key
medida - genéralo localmente con `claude setup-token` (requiere una suscripción activa de Claude Pro/Max)
y pega el resultado.
- Habilita **"Allow GitHub Actions to create and approve pull requests"** (Settings → Actions → General →
Workflow permissions) para que el workflow pueda abrir su PR. Recomendado: añade una regla de protección de rama en `main`
que requiera un PR y una revisión aprobatoria, para que ningún cambio automatizado pueda aterrizar sin un humano incluso con
el auto-merge activado.
- Para cambiar qué fuentes están permitidas, edita la allowlist en `trusted-sources.md` **y** las entradas
`WebFetch(domain:...)` correspondientes en el workflow - mantén ambas sincronizadas.
Cada ejecución registra lo que hizo en `.github/kb-update/last-run-summary.md`.
## Roadmap
- ~~Cableado del espejo de Codex / Cursor.~~
✅ Publicado: `AGENTS.md`, una extensión de Gemini CLI y `scripts/sync-agent-skills.py`
para `.agents/skills` y opencode. Ver [`docs/DISTRIBUTION.md`](https://github.com/dmdhrumilmistry/security-harness/blob/main/docs/DISTRIBUTION.md).
- ~~Aumento opcional con obtención en vivo de las bases de conocimiento (PortSwigger/OWASP/CWE) sobre las referencias curadas.~~
✅ Publicado como el actualizador programado de la base de conocimiento de arriba.
- Puente DAST opcional para la confirmación en tiempo de ejecución de hallazgos `needs-runtime`.
## Licencia
MIT