Skip to content

fix(security): el scaffolder recibe el nombre validado, no una relectura de la petición (CodeQL #226) - #750

Merged
beyondnetPeru merged 1 commit into
developfrom
security/codeql-path-injection-scaffolder-name
Sep 19, 2026
Merged

beyondnetPeru merged 1 commit into
developfrom
security/codeql-path-injection-scaffolder-name

Conversation

@beyondnetPeru

Copy link
Copy Markdown
Contributor

Cierra la última alerta CodeQL abierta sobre main (#226, js/path-injection, node-filesystem.provider.ts:50).

El flujo (SARIF de main, no el tab)

POST /projects/initialize → body.name → InitializeProjectUseCase.execute → ProjectScaffolderService.scaffoldDotnet:188 (${projectDir}/${input.name}.csproj) → NodeFileSystemProvider.writeFile.

La guarda de #725/#737 sanea el alias local name en la forma canónica (includes('..') + isAbsolute), pero el scaffolder relee input.name del objeto de la petición y CodeQL rastrea el campo aparte del alias.

Qué cambia

  • El caso de uso reconstruye la entrada con el valor validado (safeInput = { ...input, name }) y es eso lo que reciben scaffoldEvolithYaml/scaffoldReadme/scaffoldByRuntime/scaffoldCommitConventions; las etiquetas de artifacts usan name. No queda ninguna lectura de input.name aguas abajo de la guarda.
  • Test nuevo (TOCTOU real, no solo la forma que CodeQL modela): un name con getter que responde honest a la guarda y ../escape después → lo escrito es /tmp/honest/honest.csproj, sin .. en rutas ni artefactos.

Verificación

  • initialize-project.use-case.spec.ts: 18/18 (17 previos + 1 nuevo).
  • La alerta se cierra cuando corra CodeQL SAST por push sobre main (gh workflow run sdk-cli-ci.yml --ref main tras la promoción, porque el trigger por paths no cubre core-domain).

🤖 Generated with Claude Code

…o una relectura de la petición

Última alerta CodeQL abierta sobre main (#226, js/path-injection en
node-filesystem.provider.ts:50). El flujo del SARIF: POST /projects/initialize
→ body.name → InitializeProjectUseCase → ProjectScaffolderService:188
(`${projectDir}/${input.name}.csproj`) → writeFile.

La guarda de #725/#737 sanea el alias local `name` (regex + `includes('..')`
+ `isAbsolute`), pero el scaffolder vuelve a leer `input.name` del objeto de
la petición, y CodeQL rastrea el campo del objeto aparte del alias. Ahora el
caso de uso reconstruye la entrada con el valor validado (`safeInput`) y es
eso lo que llega al scaffolder; las etiquetas de `artifacts` también usan
`name`. Ninguna otra lectura de `input.name` queda aguas abajo.

No es solo la forma que CodeQL modela: un objeto cuya `name` responda una
cosa a la guarda y otra al scaffolder (getter, proxy) es un TOCTOU real, y el
test nuevo lo ejercita: el segundo read devuelve `../escape` y aun así lo
escrito es `/tmp/honest/honest.csproj`, sin `..` en ninguna ruta ni artefacto.

Verificado: spec 18/18 (17 previos + 1 nuevo), tsc sin errores en el fichero.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@beyondnetPeru
beyondnetPeru requested a review from a team as a code owner September 19, 2026 12:50
@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

Copy link
Copy Markdown
Contributor

📊 Bilingual Coverage Impact

PR Changes

  • Paired EN/ES files modified: 0
  • 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
beyondnetPeru merged commit 9eb96e1 into develop Sep 19, 2026
52 checks passed
@beyondnetPeru
beyondnetPeru deleted the security/codeql-path-injection-scaffolder-name branch September 19, 2026 13:10
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