Skip to content

fix(security): cerrar lo importante del tab Security — CWE-78/22/1321, ReDoS y permisos de workflows - #725

Merged
beyondnetPeru merged 3 commits into
developfrom
security/codeql-scorecard-triage-2026-09-19
Sep 19, 2026
Merged

beyondnetPeru merged 3 commits into
developfrom
security/codeql-scorecard-triage-2026-09-19

Conversation

@beyondnetPeru

Copy link
Copy Markdown
Contributor

Qué cierra

Triaje del tab Security (95 alertas abiertas: 75 CodeQL + 20 Scorecard) con el SARIF de la última corrida en main, no con el listado del tab. Se arregla lo que un llamador autenticado podía explotar; el resto se descarta con motivo en el propio tab.

Arreglado (código)

Alerta Dónde Fix
js/shell-command-constructed-from-input ×11 NxWorkspaceStrategy, git-log-reader argv sin shell (executeFileOrThrow, nuevo en el puerto ICommandExecutor) + allowlist de identificadores para apiName/hostName/remotes/domains del tool MCP evolith-scaffold
js/path-injection ×9 node-filesystem.provider ← controladores de core-api POST /evaluate legacy contiene satellitePath/corePath bajo WORKSPACE_ROOT/CORE_PATH (antes llegaban al fs tal cual); validate-satellite fija las rutas del manifest a las resueltas; projects/initialize valida name como segmento de directorio
js/prototype-pollution-utility evolith-config-set rechaza __proto__/constructor/prototype, solo desciende por propiedades propias
js/polynomial-redos ×8 5 sitios /\/+$/, =+$, tokenizer, parseRepoUrl trim char a char (15 s → 0 ms en 200k barras); parseRepoUrl anclado al host
js/regex/missing-regexp-anchor satellite adopt anclado
Scorecard Token-Permissions ×7 7 workflows contents: read arriba, escritura declarada por job (packages en docker, contents en docs-release/upload-assets, pull-requests: read para el guard 50)

Descartado (con motivo en el tab, tras este PR)

  • insufficient-password-hash ×9: sha256 es la normalización de longitud previa a timingSafeEqual, no almacenamiento de contraseñas.
  • user-controlled-bypass ×3: cadena de auth con comparación constante; la condición "controlada por el usuario" es qué credencial presentó.
  • clear-text-logging: el flujo tainta options entero por tener apiKey; lo que se loguea es correlationId.
  • http-to-file-access ×4, file-system-race ×3, insecure-temporary-file ×3: por diseño (registro de satélites, caché por mtime, rutas elegidas por el usuario / tests).
  • path-injection ×7 en un integration.spec, unused-local-variable ×13, unneeded-defensive-code ×2: tests / no seguridad.
  • Scorecard Binary-Artifacts ×8 (.wasm compilados del Rego contiguo, paridad en opa-parity.yml), Pinned-Dependencies ×2 (npm install -g de nuestro propio paquete a versión exacta), Fuzzing, CII, Code-Review: no son código.

Verificación

  • tsc -b limpio en los 11 proyectos.
  • Jest en los paquetes tocados: core-domain 75, mcp-server 12 (+2 nuevos: argv real y rechazo de api; rm -rf /), core-api 71 (+4 nuevos de contención), agent-runtime 85, infra-providers 21, CLI 133.
  • ESLint sobre los ficheros tocados: mismos 8 errores preexistentes (max-lines/max-params/complexity) que en develop, ninguno nuevo.

Las alertas de CodeQL se cierran cuando la corrida sobre main deje de verlas: hace falta la promoción develop→main después de este merge.

🤖 Generated with Claude Code

…, ReDoS y permisos de workflows

CodeQL (main, 75 resultados) y Scorecard, triados a mano con el SARIF: se arregla
lo que un llamador autenticado podía explotar y se descarta lo que no lo es.

CWE-78 · inyección de shell (11 alertas)
- `NxWorkspaceStrategy` interpolaba `apiName`, `hostName`, `remotes` y `domains`
  (entrada del tool MCP `evolith-scaffold`, sin validar) en una línea de shell.
  Ahora construye argv y lo ejecuta sin shell (`executeFileOrThrow`), y además
  exige que cada nombre sea un identificador plano: `--directory=apps/../..`
  y `--name=--flag` se rechazan antes de spawnear nada.
- `ICommandExecutor` gana `executeFile`/`executeFileOrThrow`; el ejecutor del
  CLI ya lo tenía y el del MCP lo implementa con `execFile`. Se elimina el
  bloque duplicado de la interfaz (TS los fusionaba en silencio).
- `git-log-reader` pasa `--since`/`--max-count` como argv.

CWE-22 · path injection en core-api (9 alertas en el adaptador de fs)
- `POST /evaluate` legacy leía `body.satellitePath`/`body.corePath` tal cual
  (el DTO decía "path traversal validation required" y nadie la hacía): el
  resolver los contiene bajo WORKSPACE_ROOT / CORE_PATH, y una instancia sin
  resolver falla cerrada.
- `POST /architecture/validate-satellite`: el manifest manda en el caso de uso
  y traía sus propias rutas; se fijan a las resueltas.
- `POST /projects/initialize`: `name` es un segmento de directorio, no una ruta
  (DTO + caso de uso, que también sirve al CLI).

CWE-1321 · prototype pollution: `evolith-config-set` rechaza `__proto__`,
`constructor` y `prototype` como segmentos y solo desciende por propiedades
propias.

ReDoS (8) · `/\/+$/` tardaba 15 s en 200k barras; se sustituye por el trim
char a char que `codeowners.ts` ya usaba. `parseRepoUrl` queda anclado al
host. El check de URL de `satellite adopt` se ancla al inicio.

Scorecard Token-Permissions (7 workflows): `contents: read` arriba y la
escritura declarada en el job que la hace (packages en docker, contents en
docs-release y upload-assets, pull-requests:read para el guard 50).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@beyondnetPeru
beyondnetPeru requested a review from a team as a code owner September 19, 2026 09:52
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions

github-actions Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

📊 Bilingual Coverage Impact

PR Changes

  • Paired EN/ES files modified: 1
  • New EN files needing ES translation: 0

Repository Coverage

Metric Value
Total EN files 527
Total ES files 497
Paired files 0
Coverage 0%

✅ Good: All EN changes have ES counterparts.


Generated by GitHub Actions

beyondnetPeru and others added 2 commits September 19, 2026 05:03
…ad aged out again

`09-reconcile-maturity.mjs` accepts evidence 0..30 days old; the 2026-08-18 entries hit
32 on 2026-09-19 and turned `Validate documentation` (a REQUIRED check) red on every
pull request opened today (#722-#725) and on the main push 99b5325 — none of which
touched what the evidence describes. Same failure mode as 3e5aac8, one month later.

Fresh observations of the same four claims, not date bumps:

- cli-baseline: run 35435871033 on cb2c8a1 (this PR), all THIRTEEN CLI CI jobs green.
- coverage: same run — 107 suites / 1492 tests, Branches 75.69% (2382/3147) against the
  unchanged 75% threshold.
- documentation: the latest green Documentation Validation is 34998373244 on the develop
  head 4d65574 (2026-09-15); every run today is red for exactly this staleness.
- release: run 35435871089 on cb2c8a1 — binaries packaged and smoke-tested on the three
  platforms; publish/upload skipped by design on a pull request.

The commits are ones a pull-request checkout can resolve (`git cat-file`): main's head
99b5325 is NOT reachable from develop yet, so citing it would have failed the guard with
"references an unavailable commit". `asOf` stays 2026-09-05 with the board, so the
reconciliation is regenerated but nothing downstream of the board date moves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Conflict on the two maturity evidence files: another session refreshed the same four
aged-out checks in 2ee3f9a (via #724) minutes before 93a90f9 did. develop's refresh
wins outright — one observation per aging, not two — so this branch now carries no
evidence change of its own; 09-reconcile-maturity --check and guard 46 pass on the result.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant