Redact live-streamed subprocess output in System.run()

Abierto
#247 0 comentarios 0 reacciones 0 asignados Ver en GitHub

@armadavalor ya está trabajando en esto.

Desde el 25/10/2026.

  • #304 de @armadavalor — abierto

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
72/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
typescript
Área
cli, security

Línea de trabajo

Comienza con src/model/system/system.ts para rastrear la ruta de escritura de stdout/stderr en vivo; después, lee src/model/secret-redaction.ts y el hilo de revisión sobre el comportamiento de redacción existente. Prueba un secret dividido entre dos chunks del stream y verifica que la salida transmitida se redacted mientras runResult.output permanece sin cambios; cubre también la ruta sin secrets.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Context

game-ci/cli#246 added the first secret redaction in src/. Before it, nothing anywhere redacted anything.

That PR covers the paths where secrets are formatted for logging:

  • the logger's formatArgs (so whole-object logs like cli.ts's parsed: dump and loadConfig's cliOptions are scrubbed)
  • the docker run command string logged at -vv
  • System.run's captured-output debug dump, redacted before truncation

It deliberately does not cover live-streamed subprocess output.

The gap

System.run() defaults to silent: false, so Docker.run() writes the child's stdout/stderr straight through to CI logs as it arrives. Those chunks are never redacted.

This is not a regression — that output was equally unredacted before #246 — but it is the one remaining place a registered secret can reach a log.

Why it wasn't fixed in #246

Doing it correctly is more than wrapping each chunk in SecretRedaction.redact():

  1. Chunk boundaries. A secret can be split across two data events, so a naive per-chunk redact misses it. It needs a retained tail of at least maxSecretLength - 1 bytes carried between chunks.
  2. Throughput. This stream carries whole Unity build logs (multi-MB). A regex pass per registered secret per chunk is a real cost on the hot path, unlike the -vv-gated paths #246 touched.
  3. Fidelity. runResult.output should stay unredacted so callers such as UnityBuildValidation.validateBuild keep matching on the true text. Only what is written out should change.
Suggested approach
  • A small streaming redactor holding a carry-over tail sized from the longest registered secret.
  • Apply it only on the write-out path, leaving runResult.output untouched.
  • Skip the work entirely when no secrets are registered, which is the common case and already how SecretRedaction.redact behaves.
  • Test: a secret deliberately split across two chunk boundaries.
References
Lenguaje dominante
TypeScript
Estrellas
20
Forks
11
Merge medio
5 h 28 min
PR fusionados (30 d)
4

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de game-ci/cli

Todos los issues de game-ci/cli

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.