- Una detección es una aparición de una vulnerabilidad en un escaneo, tal como la reportó ese escaneo: el archivo y la línea, el paquete y el CVE, o la regla de IaC. Cada escaneo genera detecciones nuevas con ids nuevos. Los endpoints del grupo Gestión de hallazgos (Issues) devuelven detecciones; una incidencia (issue) y una detección son lo mismo.
- Un finding es la vulnerabilidad en sí, dentro de un proyecto y a lo largo de todos los escaneos que la detectaron. Tiene un único id que no cambia entre escaneos, y es donde vive el triaje: estado, comentario, responsable, fecha de caducidad del riesgo aceptado, fecha límite y SLA.
/detections es la misma API que /issues, con un nombre nuevo. Cada endpoint del grupo Gestión de hallazgos (Issues) también se sirve bajo /detections, con el mismo código, los mismos parámetros y la misma respuesta. La llamamos /detections porque «issue» se confundía fácilmente con un finding: cada resultado es la detección de una vulnerabilidad en un escaneo, no la vulnerabilidad en sí. Usa /detections en las integraciones nuevas. /issues sigue siendo compatible, así que las integraciones existentes no necesitan cambios.Pasar de un nivel al otro
Cada elemento de detección incluye elfinding_id de su finding. Agrupa las detecciones por ese campo, nunca por first_detection_date, que es una propiedad del finding y no una clave. El campo solo es null en las detecciones ingeridas antes de que existieran los findings.
Cada finding incluye latest_detection: su detección más reciente, con el id que aceptan los endpoints de detecciones y el localizador propio de cada familia (file_path y line_number; path, package, version y cve; o path, rule_id, start_line y end_line).
Un cambio de triaje hecho en cualquiera de los dos niveles se aplica al finding y, por tanto, a todas sus detecciones.
Qué endpoint llamar
Los endpoints de detecciones
/detections es el nuevo nombre de los endpoints del grupo Gestión de hallazgos (Issues), no una API distinta. Cada uno de ellos responde bajo ambas rutas:
Ambas rutas ejecutan el mismo código y devuelven la misma respuesta, incluidas las claves
issues y total_issues. Usa /detections en las integraciones nuevas; /issues sigue siendo compatible.
Los endpoints de findings
GET /api/v1/findings devuelve una fila por finding, de más reciente a más antiguo según su primera detección, paginada con page y page_size (hasta 100) y con un recuento total_findings. Salvo que se indique lo contrario, los filtros aceptan listas separadas por comas:
No existe un filtro
branch: un finding pertenece a un proyecto, y la rama es una propiedad de sus detecciones. El token necesita el mismo permiso de visualización que la lista de detecciones de la familia; indicar una familia que no puede ver devuelve un 403.
GET /api/v1/findings/{finding_id} devuelve un finding con la misma estructura: sus campos de triaje, urgency, classification, project, detection_state, first_detection_date, last_detection_date, detections_count y latest_detection.
detection_state
Un finding está active mientras tenga una detección en su proyecto, y pasa a retired cuando su última detección se elimina junto con su escaneo o su proyecto. Un finding que un reescaneo ya no reporta no se retira: sigue active y su status pasa a fixed. Un finding retirado conserva su triaje, de modo que una detección que reaparece se asocia al mismo id de finding y hereda la misma decisión.
detection_state es null, y GET /api/v1/findings responde 404, hasta que el índice de findings de la cuenta esté completo. Los endpoints de detecciones y GET /api/v1/findings/{finding_id} no se ven afectados.Triaje por finding
PATCH /api/v1/triage/findings acepta finding_ids: una lista de ids de finding (obtenidos de GET /api/v1/findings o del finding_id de los elementos de detección) o de ids de detección. Un id de finding equivale a la detección más reciente del finding, y la decisión alcanza a todas sus detecciones. Los ids que no resuelven a nada se devuelven en unresolved_ids y cuentan como no coincidentes, así que un lote con un id obsoleto aplica igualmente el resto. El triaje masivo abarca las familias SAST, secretos, lógica, calidad de código y dependencias; un id de contenedor o de IaC se devuelve en unresolved_ids, y las filas de auditoría indican finding_type como sast o sca.
Una rule puede incluir un ámbito statuses, de modo que una sola llamada puede, por ejemplo, pasar a falso positivo todos los findings que hoy son riesgo aceptado.
Un bucle de sincronización
Usa el id del finding como clave del ticket. El id de una detección cambia con cada escaneo; el de un finding, no. Cada ejecución lee tres listas y escribe un lote. Todas las listas están paginadas: pidepage=1, 2, … con page_size=100 hasta que page alcance total_pages. Guarda la hora de inicio de la ejecución como fecha y hora ISO 8601 completa en UTC, y pásala como <last run> la próxima vez.
GET /api/v1/findings?created_since=<last run>: abre un ticket por cada finding nuevo. Un finding nuevo aún no tiene cambios de triaje, así que el paso 2 no lo devuelve.GET /api/v1/findings?status_changed_since=<last run>&detection_state=all: aplica los cambios de triaje, incluidos los de findings retirados. Un finding cuyostatuspasó afixedcierra su ticket.GET /api/v1/findings?detection_state=retired: concilia los findings retirados. La retirada no registra ninguna hora ni cambia el estado, así que ninguno de los dos cursores la devuelve. Compara esta lista completa con tus tickets abiertos y cierra o marca los que aparezcan. Si una detección reaparece, el finding vuelve a estaractivecon el mismo id.PATCH /api/v1/triage/findingsconfinding_ids: envía a Corgea las decisiones tomadas en el sistema de tickets. Leeunresolved_idsincluso con un200. Esos ids, entre ellos todos los findings de contenedores e IaC, no se actualizaron, mientras que el resto del lote sí.
issue_type a cada llamada de lista si sincronizas findings de calidad de código, que el valor por defecto excluye. Un 404 de GET /api/v1/findings significa que el índice de findings de la cuenta aún no está completo, no que no haya nada que sincronizar. Vuelve a intentarlo más tarde y conserva el cursor anterior.