
Documenta CVE-2026-65320, un path traversal de tipo tar-slip en untar_dir() de fastcore, con una prueba de concepto inofensiva que demuestra escritura arbitraria de archivos y ejecución de código.
untar_dir()Severidad: Crítica, CVSS 3.1 9.8
Vector (v3.1): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Afecta a: fastcore <= 2.2.30
Corregido en: No corregido en el momento de redacción
CWE: CWE-22 (Limitación incorrecta de un nombre de ruta a un directorio restringido, 'Path Traversal')
Componente: fastcore.xtras.untar_dir() → fastcore.xtras._unpack() → shutil.unpack_archive()
Entorno de ejecución de alto riesgo: Python < 3.14 (Python 3.14 hace que el filtro tar seguro data sea el predeterminado)
Reportado por: Rahul Karne
CNA: VulnCheck
fastcore.xtras.untar_dir(fname, dest) es un helper documentado que descomprime un archivo tar "en dest".
Internamente, entrega el archivo a shutil.unpack_archive() de la biblioteca estándar sin un filtro de extracción, sin validar las rutas de los miembros del archivo y sin ninguna comprobación de contención posterior a la extracción.
Como resultado, un archivo TAR cuyos miembros contienen secuencias de traversal ../ o rutas absolutas puede escribir archivos fuera del directorio en el que el llamador pidió a fastcore que extrajera.
Un llamador que razonablemente espera que untar_dir(fname, dest) confine todo a dest en su lugar obtiene escritura arbitraria de archivos en cualquier lugar donde el proceso pueda escribir.
Escritura arbitraria de archivos bajo la autoridad del proceso que llama a untar_dir().
Dependiendo de lo que se sobrescriba, esto puede dar lugar a:
La prueba de concepto demuestra la cadena completa escritura → importación → ejecución de código de principio a fin, enteramente dentro de un directorio de demostración inofensivo.
fastcore es una dependencia fundamental en todo el ecosistema fast.ai, incluyendo:
fastainbdevghapiRecibe decenas de millones de descargas al mes.
untar_dir() es la primitiva de extracción detrás del flujo de trabajo común "descargar un archivo, luego descomprimirlo", que sigue el mismo patrón general que untar_data de fastai.
Cualquier ruta de código que alimente a untar_dir() con un archivo cuyo contenido no sea totalmente confiable queda expuesta.
El código vulnerable existe en fastcore/xtras.py:
def _unpack(fname, out):
import shutil
shutil.unpack_archive(str(fname), str(out)) # <-- no filter, no validation
ls = out.ls()
return ls[0] if len(ls) == 1 else out
def untar_dir(fname, dest, rename=False, overwrite=False, uid=-1, gid=-1):
"untar `file` into `dest` ..."
import tempfile, shutil
dest = Path(dest)
with tempfile.TemporaryDirectory() as d:
out = Path(d) / remove_suffix(Path(fname).stem, '.tar')
out.mkdir()
...
src = _unpack(fname, out) # extraction escapes `out` here
...
shutil.move(str(src), dest)
...
return dest
untar_dir() crea un directorio temporal interno de extracción:
<tempdir>/<random>/<archive-stem>/
Luego llama a _unpack(), que reenvía el archivo directamente a:
shutil.unpack_archive()
Para archivos TAR, esto finalmente llama a tarfile.extractall().
En Python < 3.14, el comportamiento de extracción predeterminado es fully_trusted, lo que significa que los miembros con traversal pueden ser aceptados.
Por ejemplo, un miembro del archivo como:
../../../some/other/dir/file
se escribe en relación con el directorio de extracción y, por lo tanto, puede escapar de él.
Nada en fastcore:
filter="data" donde es compatible....untar_dir() trata a shutil.unpack_archive() como si fuera un extractor de archivos seguro y en sandbox.
No lo es.
La documentación de la biblioteca estándar de Python advierte que extraer archivos no confiables puede crear archivos fuera del destino solicitado y recomienda un filtrado de extracción seguro para archivos TAR.
fastcore ni pasa un filtro de extracción apropiado ni implementa una protección de contención equivalente para las versiones de Python que soporta.
Tampoco advierte a los llamadores de untar_dir() sobre este comportamiento sensible a la seguridad.
Los miembros TAR pueden contener cadenas de ruta arbitrarias.
En las versiones de Python afectadas, tarfile.extractall() no neutraliza automáticamente las secuencias de traversal .. de forma predeterminada.
Escribir un miembro con traversal en relación con el directorio temporal de extracción de fastcore es, por lo tanto, suficiente para escapar de ese directorio y escribir en cualquier lugar donde el proceso tenga permiso de escritura.
Una primitiva fiable es el traversal relativo como:
../../../target/file
Esta es la técnica utilizada por la prueba de concepto.
La entrada peligrosa es el contenido del archivo, no la ruta de destino elegida por el desarrollador.
Los archivos se obtienen con frecuencia de ubicaciones externas o semiconfiables, incluyendo:
Cualquier servicio o herramienta que descargue un archivo de una fuente no confiable o semiconfiable y posteriormente lo procese usando untar_dir() puede, por lo tanto, ser alcanzable.
La PoC también incluye una variante que sirve el archivo manipulado desde un endpoint HTTP controlado por el atacante para demostrar esta ruta de entrega.
La explotación exitosa requiere:
La aplicación llama a fastcore.xtras.untar_dir() sobre un archivo cuyo contenido está influenciado por el atacante, como un archivo subido, descargado o de otro modo no confiable.
El entorno de ejecución usa Python < 3.14, u otra configuración donde no se aplique un filtro de extracción TAR seguro.
Para la escalada de escritura arbitraria de archivos a ejecución de código, el proceso posteriormente importa o carga un archivo desde una ubicación alcanzable por el traversal, como:
La escritura arbitraria de archivos y la modificación de configuración/datos requieren solo las condiciones 1 y 2.
poc_fastcore_cna_demo.py invoca la API real fastcore.xtras.untar_dir().
La demostración es intencionadamente inofensiva.
Cada archivo creado por la PoC permanece dentro de un único directorio de demostración especificado usando:
--demo-root
La PoC no modifica archivos reales del sistema y no accede a servicios en la nube ni a credenciales.
Imprime los detalles del entorno y el código fuente vulnerable de _unpack() y untar_dir().
Crea una estructura de demostración que contiene:
service_app/plugins/
Crea:
attacker_supplied_upload.tar
que contiene miembros del archivo diseñados para apuntar fuera de la raíz de extracción prevista, incluyendo miembros con traversal y:
service_app/plugins/startup_hook.py
def auto_extract_uploaded_archive(received_archive):
return untar_dir(
received_archive,
intended_root,
overwrite=True
)
Verifica que los archivos se escribieron fuera del directorio de extracción previsto.
Simula una recarga del servicio importando el archivo escrito por el archivo:
startup_hook.py
El hook de inicio inofensivo crea:
SERVICE_RELOAD_MARKER
Esto demuestra la cadena completa:
Attacker-controlled archive
↓
Path traversal during extraction
↓
Arbitrary file write
↓
Write into importable / auto-loaded location
↓
Application loads attacker-controlled file
↓
Code execution
Instala el paquete afectado:
pip install fastcore
El problema ha sido confirmado a través de:
fastcore 2.2.30
La demostración puede ejecutarse contra:
fastcore instalada con pip--sourceTodas las escrituras de la PoC permanecen dentro del directorio especificado mediante --demo-root.
Limpia cualquier salida previa de la PoC:
python poc_fastcore_cna_demo.py --demo-root ./poc_fastcore --clean
Ejecuta la demostración:
python poc_fastcore_cna_demo.py \
--demo-root ./poc_fastcore \
--source latest \
--no-pause
Ejemplo de salida abreviada:
fastcore version: 2.2.30
Outside marker exists after extraction? True
Is outside marker inside intended extraction root? False
Relative traversal marker exists after extraction? True
Is relative traversal marker inside intended extraction root? False
Service plugin file exists after extraction? True
Service reload marker exists? True
POC WORKED: fastcore extracted attacker-controlled tar members outside the intended root.
En las versiones de Python compatibles, usa un filtro de extracción seguro como:
filter="data"
con shutil.unpack_archive() o la operación de extracción tarfile correspondiente.
Cada miembro del archivo debe comprobarse antes de la extracción.
Rechazar:
..Los destinos de los enlaces también deben resolverse y validarse antes de la extracción.
Resuelve cada ruta de destino antes de escribir y verifica que permanezca bajo la raíz de extracción prevista.
Conceptualmente:
resolved_member_path
↓
must remain inside
↓
resolved_extraction_root
La extracción debe fallar si el destino resuelto escapa de la raíz de extracción.
Las pruebas de regresión deben cubrir al menos:
../ traversal
absolute paths
Windows drive-letter paths
UNC paths
symbolic links
hard links
Documenta claramente si untar_dir() está destinado a procesar de forma segura archivos no confiables.
Si la extracción insegura se soporta intencionadamente, el comportamiento seguro debería seguir siendo el predeterminado.
El comportamiento inseguro debería requerir una adhesión explícita en lugar de confiar silenciosamente en el contenido del archivo.
Hasta que se publique una corrección a nivel de paquete:
untar_dir().El defecto técnico subyacente es una vulnerabilidad de escritura arbitraria de archivos causada por el path traversal en la extracción de archivos.
Sin embargo, la severidad final depende del entorno de despliegue y de cómo se expone untar_dir().
Un vector representativo puede acercarse a:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Resultado:
9.8 — Critical
Si la explotación en su lugar requiere que un desarrollador descargue y extraiga manualmente un archivo, la interacción del usuario y la complejidad del ataque pueden ser mayores.
La puntuación CVSS resultante sería, por lo tanto, materialmente inferior.
Deben considerarse dos factores importantes al evaluar el problema.
Esta es una instancia de la clase de vulnerabilidad de extracción TAR insegura conocida desde hace mucho tiempo asociada con:
CVE-2007-4559
Las versiones modernas de Python han introducido un comportamiento de extracción de archivos más seguro.
Python 3.14 hace que el filtro de extracción seguro data sea el predeterminado.
Por lo tanto, el entorno principalmente afectado es Python < 3.14.
Sin embargo, esos entornos de ejecución siguen estando ampliamente desplegados.
La vulnerabilidad se vuelve explotable cuando un llamador proporciona a untar_dir() un archivo cuyo contenido está controlado por el atacante o de otro modo no es confiable.
Este informe, por lo tanto, trata el contenido del archivo como el límite de seguridad no confiable.
Un helper robusto de extracción de archivos debería fallar de forma segura independientemente de cómo se obtuvo el archivo.
Reemplaza las fechas de marcador de posición a continuación con las fechas reales de divulgación.
YYYY-MM-DD — Vulnerabilidad reportada a los mantenedores.YYYY-MM-DD — Respuesta del proveedor / acuse de recibo / sin respuesta.2.2.30); el código de extracción permaneció sin cambios.Descubierto y reportado por Rahul Karne.
Documentación de untar_dir() de fastcore
https://fastcore.fast.ai/xtras.html
Código fuente de xtras.py de fastcore
https://github.com/AnswerDotAI/fastcore/blob/main/fastcore/xtras.py
fastcore en PyPI
https://pypi.org/project/fastcore/
Documentación de shutil.unpack_archive() de Python
https://docs.python.org/3/library/shutil.html#shutil.unpack_archive
Filtros de extracción de tarfile de Python
https://docs.python.org/3/library/tarfile.html#extraction-filters
PEP 706 — Filtro para tarfile.extractall
https://peps.python.org/pep-0706/
CWE-22 — Limitación incorrecta de un nombre de ruta a un directorio restringido
https://cwe.mitre.org/data/definitions/22.html
CVE-2007-4559 — Clase de vulnerabilidad de extracción TAR insegura
https://nvd.nist.gov/vuln/detail/CVE-2007-4559
Este repositorio documenta un hallazgo de seguridad de divulgación coordinada y proporciona una prueba de concepto inofensiva y autocontenida.
La PoC escribe solo dentro del directorio --demo-root especificado por el usuario y no realiza acciones destructivas.
Cualquier funcionalidad de red incluida en la demostración se limita a una demostración local opcional.
Este material se proporciona para investigación de seguridad defensiva y fines educativos.
Consultas de medios: [email protected]. PoC completa (servidor atacante, archivo con traversal, aplicación víctima) y detalle técnico adicional disponibles bajo petición.