codaprobe: prueba de la app viva
codaprobe prueba una aplicación viva por la red, solo en los objetivos que un archivo de alcance autoriza; la ambigüedad en el alcance es rechazo.
Antes de que salga cualquier paquete, el objetivo debe estar en la allowlist del alcance. Por eso esta guía empieza por la autorización.
Licencia. En el binario público,codaproberequiere licencia Pro, Verified o Platform (Vibe no incluye runtime). Sin ella, sale con código40(el3es rechazo de alcance).check-scope,schemayverify-auditsiguen libres. Antes del lanzamiento todavía no se acepta ninguna licencia: el binario público sale con40incluso con token. Ver planes.
1. Autorización y alcance (lee antes de correr)
El alcance es un JSON que declara quién autorizó y qué está autorizado:
{
"authorization": {
"attestation": "pentest autorizado — ticket SEC-4210, aprobado por Maria Silva (CISO) el 2026-07-20",
"granted": true
},
"entries": [
{ "host": "app.cliente.test", "port": 443, "path_prefix": "/api", "mutating_opt_in": false }
]
}
| Campo | Significado | Si está mal |
|---|---|---|
attestation | texto libre de procedencia (quién, ticket, fecha); va al informe | el informe pierde valor como evidencia |
granted | el operador declara la autorización; ausente = false | todo se rechaza |
host · port | objetivo en forma canónica, puerto explícito | forma no canónica reprueba la carga; un puerto distinto se rechaza |
path_prefix | prefijo casado por segmento completo (/api cubre /api/x, no /apix); obligatorio | una clave mal escrita reprueba la carga, en lugar de autorizar el host entero |
mutating_opt_in | libera POST/PUT/PATCH/DELETE en este objetivo; ausente = false | el método mutante se rechaza antes de la red |
Un campo desconocido reprueba la carga: un error de tipeo no puede convertirse en permiso. Verifica sin tocar la red:
codaprobe check-scope --scope alcance.json --url https://app.cliente.test/api/
2. Escanear
# pasivo — solo el tráfico legítimo, ningún payload (headers, cookies, CORS, fugas)
codaprobe scan --scope alcance.json --url https://app.cliente.test/api > informe.json
# activo, dirigido por el contrato (OpenAPI 3 JSON/YAML, colección Postman o HAR)
codaprobe scan --scope alcance.json --url https://app.cliente.test/api \
--contract openapi.yaml --active --auth-file auth.txt --audit-out audit.json > informe.json
# sin contrato: descubre la superficie por crawl (sin navegador)
codaprobe scan --scope alcance.json --url https://app.cliente.test --crawl --active > informe.json
# GraphQL a partir de la introspección
codaprobe scan --scope alcance.json --url https://app.cliente.test/graphql --graphql introspection.json --active
El modo activo prueba query, header, cookie, formulario, segmento de path y el nombre del parámetro. Los payloads son benignos: revelan la falla sin explotarla. Para fallas sin respuesta visible está --temporal; la detección out-of-band (--oob) viene apagada por defecto.
Flags que cambian el resultado: --rps <n> (cadencia total, por defecto 5), --concorrencia <n> (concurrencia), --fail-on <sev> (reprueba solo por finding confirmado), --ca-cert <pem> (prefiérelo a --insecure, que también apaga la verificación de hostname), --correlate-src <envelope> (cruza con el envelope de codafort).
3. El informe y el registro de auditoría
El informe es coda-dast/1: findings moment: run, URL redactada (sin userinfo ni query), el texto de la autorización y el ancla del registro de auditoría. El registro (--audit-out) está encadenado por SHA-256 y se verifica así:
codaprobe verify-audit --file audit.json --report informe.json # exit 0 INTACT · 21 TAMPERED
Con --report (o --expect-anchor), el comando verifica el registro contra el ancla del informe y responde INTACT (exit 0) o TAMPERED (exit 21). Sin ellos, el mejor veredicto posible es CONSISTENT: quien edita el registro puede recalcular la cadena, y solo el ancla del informe detecta una remoción con la cadena rehecha. Verifica siempre con el informe.
4. En el pipeline
codaprobe scan --scope alcance.json --url "$OBJETIVO" --contract openapi.yaml --active \
--auth-file auth.txt --rps 10 --fail-on high --audit-out audit.json > informe.json
Solo un finding confirmado reprueba el build; un candidato no.
| Exit | Significado |
|---|---|
0 | corrió (los findings no son error) |
1 | --fail-on reprobó |
3 | objetivo rechazado por el alcance |
20 | entrada inválida (alcance, contrato, credencial, --rps absurdo) |
21 | verify-audit: cadena rota o ancla que no coincide |
30 | error de I/O o de red al arrancar |
40 | sin licencia (ver arriba) |
Lo que nunca hace
No relaja el alcance, el modo no destructivo ni la redacción de la URL para encontrar más fallas. No guarda secretos en el informe.