
Documenta CVE-2026-65320, un path traversal di tipo tar-slip in untar_dir() di fastcore, con un proof-of-concept innocuo che dimostra la scrittura arbitraria di file e l'esecuzione di codice.
untar_dir()Gravità: Critica, CVSS 3.1 9.8
Vettore (v3.1): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Interessato: fastcore <= 2.2.30
Corretto in: Non corretto al momento della stesura
CWE: CWE-22 (Limitazione impropria di un percorso a una directory ristretta, 'Path Traversal')
Componente: fastcore.xtras.untar_dir() → fastcore.xtras._unpack() → shutil.unpack_archive()
Runtime ad alto rischio: Python < 3.14 (Python 3.14 rende predefinito il filtro tar sicuro data)
Segnalato da: Rahul Karne
CNA: VulnCheck
fastcore.xtras.untar_dir(fname, dest) è un helper documentato che estrae un archivio "in dest".
Internamente, passa l'archivio alla funzione della libreria standard shutil.unpack_archive() senza un filtro di estrazione, senza validare i percorsi dei membri dell'archivio e senza alcun controllo di contenimento post-estrazione.
Di conseguenza, un archivio TAR i cui membri contengono sequenze di traversal ../ o percorsi assoluti può scrivere file al di fuori della directory in cui il chiamante ha chiesto a fastcore di estrarre.
Un chiamante che si aspetta ragionevolmente che untar_dir(fname, dest) confini tutto in dest ottiene invece una scrittura arbitraria di file ovunque il processo possa scrivere.
Scrittura arbitraria di file sotto l'autorità del processo che chiama untar_dir().
A seconda di ciò che viene sovrascritto, questo può comportare:
La proof of concept dimostra l'intera catena scrittura → import → esecuzione di codice dall'inizio alla fine, interamente all'interno di una directory demo innocua.
fastcore è una dipendenza fondamentale in tutto l'ecosistema fast.ai, tra cui:
fastainbdevghapiRiceve decine di milioni di download al mese.
untar_dir() è la primitiva di estrazione alla base del comune flusso di lavoro "scarica un archivio, poi estrailo", che segue lo stesso schema generale di untar_data di fastai.
Qualsiasi percorso di codice che alimenta untar_dir() con un archivio i cui contenuti non sono completamente attendibili è esposto.
Il codice vulnerabile esiste in 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 una directory temporanea interna di estrazione:
<tempdir>/<random>/<archive-stem>/
Poi chiama _unpack(), che inoltra l'archivio direttamente a:
shutil.unpack_archive()
Per gli archivi TAR, questo alla fine chiama tarfile.extractall().
Su Python < 3.14, il comportamento di estrazione predefinito è fully_trusted, il che significa che i membri con traversal possono essere onorati.
Ad esempio, un membro dell'archivio come:
../../../some/other/dir/file
viene scritto relativamente alla directory di estrazione e può quindi uscirne.
Nulla in fastcore:
filter="data" dove supportato....untar_dir() tratta shutil.unpack_archive() come se fosse un estrattore di archivi sicuro e sandboxed.
Non lo è.
La documentazione della libreria standard di Python avverte che estrarre archivi non attendibili può creare file al di fuori della destinazione richiesta e raccomanda un filtraggio di estrazione sicuro per gli archivi TAR.
fastcore né passa un filtro di estrazione appropriato né implementa una protezione di contenimento equivalente per le versioni di Python che supporta.
Inoltre non avverte i chiamanti di untar_dir() di questo comportamento sensibile alla sicurezza.
I membri TAR possono contenere stringhe di percorso arbitrarie.
Sulle versioni di Python interessate, tarfile.extractall() non neutralizza automaticamente le sequenze di traversal .. per impostazione predefinita.
Scrivere un membro con traversal relativamente alla directory temporanea di estrazione di fastcore è quindi sufficiente per uscire da quella directory e scrivere ovunque il processo abbia il permesso di scrivere.
Una primitiva affidabile è il traversal relativo come:
../../../target/file
Questa è la tecnica utilizzata dalla proof of concept.
L'input pericoloso è il contenuto dell'archivio, non il percorso di destinazione scelto dallo sviluppatore.
Gli archivi sono spesso ottenuti da posizioni esterne o semi-attendibili, tra cui:
Qualsiasi servizio o strumento che scarica un archivio da una fonte non attendibile o semi-attendibile e successivamente lo elabora usando untar_dir() può quindi essere raggiungibile.
La PoC include anche una variante che serve l'archivio creato ad hoc da un endpoint HTTP controllato dall'attaccante per dimostrare questo percorso di consegna.
Lo sfruttamento riuscito richiede:
L'applicazione chiama fastcore.xtras.untar_dir() su un archivio i cui contenuti sono influenzati dall'attaccante, come un archivio caricato, scaricato o altrimenti non attendibile.
Il runtime utilizza Python < 3.14, o un'altra configurazione in cui un filtro di estrazione TAR sicuro non è applicato.
Per l'escalation da scrittura arbitraria di file a esecuzione di codice, il processo successivamente importa o carica un file da una posizione raggiungibile dal traversal, come:
La scrittura arbitraria di file e la modifica di configurazione/dati richiedono solo le condizioni 1 e 2.
poc_fastcore_cna_demo.py invoca l'API reale fastcore.xtras.untar_dir().
La dimostrazione è intenzionalmente innocua.
Ogni file creato dalla PoC rimane all'interno di una singola directory demo specificata usando:
--demo-root
La PoC non modifica file di sistema reali e non accede a servizi cloud o credenziali.
Stampa i dettagli dell'ambiente e il codice sorgente vulnerabile per _unpack() e untar_dir().
Crea un layout dimostrativo contenente:
service_app/plugins/
Crea:
attacker_supplied_upload.tar