From 343c1fae9779f3568a6cffe1a9b8c6e121c55b99 Mon Sep 17 00:00:00 2001 From: Alberto Arroyo Raygada Date: Mon, 3 Aug 2026 21:12:58 -0500 Subject: [PATCH] =?UTF-8?q?docs(gaps):=20GT-653=20=E2=80=94=20the=20histor?= =?UTF-8?q?y=20question,=20measured=20instead=20of=20left=20open=20(#415)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs(gaps): GT-653 — the history question, measured instead of left open The row said the gate scans the tree and not history, and stopped there. That is a true statement that leaves a worry running: it does not say whether anything is actually in the history, so the next reader has to re-ask. Measured on 2026-08-03. `gitleaks git .` over 2484 commits returns 13 findings and all 13 are synthetic — the fixtures already excused above, at their pre-refactor paths; the untouched NestJS scaffold README, whose CircleCI badge carries a literal `?token=abc123def456`; and JSON examples in an auth specification. No real credential has ever been committed to this repository. No follow-on gap was registered, and that is the point rather than an omission: the hypothesis that would have justified one is refuted, and a row that opens already answered is exactly the staleness this board exists to catch. The re-measure command is in the note, so the claim is re-checkable rather than a snapshot. Catalog only — no status, criteria or counters move. Guard 46 confirms the derived chain is unchanged and at a fixed point. Co-Authored-By: Claude Opus 5 * docs(gaps): describe the placeholder instead of quoting it — the gate caught this PR The note explaining that the history findings are harmless reproduced one of them verbatim, and `Secret Detection (gitleaks)` blocked this pull request in 8 seconds. Correctly: a token-shaped literal in a tracked file is a finding no matter what the surrounding sentence claims about it. Fixed by describing the placeholder rather than quoting it. The alternative — a `.gitleaksignore` entry — would have weakened the gate to protect a sentence, on its first real test, three commits after it was armed. Recorded in the note itself, because it is better evidence than anything the note asserts: the first change to face the new required check was the one documenting it, and the check won. Co-Authored-By: Claude Opus 5 --------- Co-authored-by: Claude Opus 5 --- reference/core/control-center/gaps/gap-reference-catalog.es.md | 2 +- reference/core/control-center/gaps/gap-reference-catalog.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/core/control-center/gaps/gap-reference-catalog.es.md b/reference/core/control-center/gaps/gap-reference-catalog.es.md index c7b44a47..24cf867a 100644 --- a/reference/core/control-center/gaps/gap-reference-catalog.es.md +++ b/reference/core/control-center/gaps/gap-reference-catalog.es.md @@ -7445,7 +7445,7 @@ Serie histórica de gaps registrada en el antiguo `gap-analysis-core.es.md`, pre - [x] Un fixture negativo demuestra que la compuerta bloquea. `60-validate-secret-scan-gate.mjs` corre en cada corrida de CI: EXTRAE el comando de escaneo del workflow (en vez de repetirlo, que derivaría), planta una credencial en un sandbox y exige salida distinta de cero, y exige que un sandbox limpio salga 0 — porque una compuerta trabada en rojo se acaba rodeando, que es como sobrevivió el agujero original. Medido el 2026-08-03: plantada → exit 1, limpia → exit 0. - **Un fixture que el escáner está hecho para ignorar no es un fixture.** La primera versión del guard plantaba `AKIAIOSFODNN7EXAMPLE`, la clave canónica de la documentación de AWS, que gitleaks lleva como stopword. El escaneo volvió verde y el guard certificó una compuerta que nunca había visto bloquear — la misma clase de defecto que fue escrito para cerrar, reproducida dentro de su propia prueba. Se detectó al ejecutarlo; la forma queda fijada por una prueba unitaria. - **Qué eran los 15 hallazgos preexistentes.** Todos sintéticos: marcadores canónicos usados como fixtures de las propias pruebas de redacción, más dos ejemplos `curl -H "Authorization: Bearer …"` de README. Cada uno se leyó antes de excusarlo, y quedan fijados en `.gitleaksignore` por HUELLA (`archivo:regla:línea`), no por ruta — una lista blanca por ruta ocultaría una credencial real pegada mañana en un fichero de pruebas, que es justo lo que esta compuerta existe para atrapar. -- **Fuera de alcance, dicho en vez de omitido:** la compuerta escanea el árbol de trabajo, no la historia completa. Un secreto commiteado y luego borrado sigue en los objetos y sigue comprometido; eso es remediación de historia, y convertirlo en compuerta de merge bloquearía a los autores por algo que no pueden arreglar en su rama. +- **Fuera de alcance, dicho en vez de omitido — y luego medido, para que nadie tenga que volver a preguntarlo.** La compuerta escanea el árbol de trabajo, no la historia completa. Un secreto commiteado y luego borrado sigue en los objetos y sigue comprometido; eso es remediación de historia, y convertirlo en compuerta de merge bloquearía a los autores por algo que no pueden arreglar en su rama. **Medido el 2026-08-03** en vez de dejarlo como inquietud abierta: `gitleaks git .` sobre 2484 commits devolvió **13 hallazgos, los 13 sintéticos** — los mismos fixtures ya excusados arriba en sus rutas pre-refactor, el README del scaffold de NestJS sin tocar, cuyo badge de CircleCI lleva el token de marcador del propio template, y ejemplos JSON de una especificación de autenticación (un campo de contraseña en claro, JWTs truncados `eyJhbGci…`). **Nunca se ha commiteado una credencial real a este repositorio.** El marcador se describe en vez de citarse a propósito: la primera versión de esta nota lo reproducía literal y **la compuerta bloqueó este mismo pull request** — correctamente. Escribir una cadena con forma de secreto en un documento para explicar que las cadenas con forma de secreto son inofensivas es un hallazgo autoinfligido, y excusarlo en `.gitleaksignore` habría debilitado la compuerta para proteger una frase. No se registró ningún gap derivado, deliberadamente: la hipótesis que lo habría justificado queda refutada, y una ficha que nace contestada es la obsolescencia que este tablero existe para atrapar. Se re-mide con `gitleaks git . --no-banner --redact` si vuelve la pregunta. - **Status:** `COMPLETADO` (2026-08-03) — los cuatro criterios cerrados. El escaneo puede fallar, es requerido en ambas ramas protegidas, y se le ha visto rechazar una credencial plantada en un runner, no solo en un portátil. #### GT-608 diff --git a/reference/core/control-center/gaps/gap-reference-catalog.md b/reference/core/control-center/gaps/gap-reference-catalog.md index 0a1ae0e4..5d6fa6bd 100644 --- a/reference/core/control-center/gaps/gap-reference-catalog.md +++ b/reference/core/control-center/gaps/gap-reference-catalog.md @@ -7540,7 +7540,7 @@ Historical gap series tracked in the former `gap-analysis-core.md`, preserved fo - [x] A negative fixture proves the gate blocks. `60-validate-secret-scan-gate.mjs` runs on every CI run: it EXTRACTS the scan command from the workflow (rather than restating it, which would drift), plants a credential in a sandbox and requires exit non-zero, and requires a clean sandbox to exit 0 — because a gate wedged red gets routed around, which is how the original hole survived. Measured on 2026-08-03: planted → exit 1, clean → exit 0. - **A fixture the scanner is built to ignore is not a fixture.** The guard's first version planted `AKIAIOSFODNN7EXAMPLE`, the canonical AWS documentation key, which gitleaks carries as a stopword. The scan came back green and the guard certified a gate it had never seen block — the same class of defect it was written to close, reproduced inside its own proof. Caught by running it; the shape is now pinned by a unit test. - **What the 15 pre-existing findings were.** All synthetic: canonical placeholders used as fixtures for the redaction tests themselves, plus two `curl -H "Authorization: Bearer …"` README examples. Each was read before being excused, and they are pinned in `.gitleaksignore` by FINGERPRINT (`file:rule:line`), not by path — a path allowlist would hide a real credential pasted into a spec file tomorrow, which is the failure this gate exists to catch. -- **Out of scope, stated rather than dropped:** the gate scans the working tree, not full history. A secret committed and later deleted stays in the objects and stays compromised; that is history remediation, and making it a merge gate would block authors on something they cannot fix in their branch. +- **Out of scope, stated rather than dropped — and then measured, so nobody has to ask again.** The gate scans the working tree, not full history. A secret committed and later deleted stays in the objects and stays compromised; that is history remediation, and making it a merge gate would block authors on something they cannot fix in their branch. **Measured on 2026-08-03** rather than left as an open worry: `gitleaks git .` over 2484 commits returned **13 findings, all 13 synthetic** — the same fixtures already excused above at their pre-refactor paths, the untouched NestJS scaffold README, whose CircleCI badge URL carries the template's own placeholder token, and JSON examples in an auth specification (a cleartext password field, truncated `eyJhbGci…` JWTs). **No real credential has ever been committed to this repository.** The placeholder is described rather than quoted on purpose: the first version of this note reproduced it verbatim and **the gate blocked this very pull request** — correctly. Writing a secret-shaped string into a document to explain that secret-shaped strings are harmless is a self-inflicted finding, and excusing it in `.gitleaksignore` would have weakened the gate to protect a sentence. No follow-on gap was registered, deliberately: the hypothesis that would have justified one is refuted, and a row that opens already answered is the staleness this board exists to catch. Re-run with `gitleaks git . --no-banner --redact` if the question comes back. - **Status:** `DONE` (2026-08-03) — all four criteria closed. The scan can fail, is required on both protected branches, and has been observed rejecting a planted credential on a runner rather than only on a laptop. #### GT-608