Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-65320-fastcore — Documents CVE-2026-65320, a tar-slip path traversal in fastcore's untar_dir(), with a harmless proof-of-concept demonstrating arbitrary file write and code execution. | Kitploit
Tools/GitHubGitHub/rahulreddykarne/cve-2026-65320-fastcore
Vulnerability AnalysisCode AnalysisExploitationWeb Application ExploitationPapers & ResearchLearning & Education
GitHubrahulreddykarne/cve-2026-65320-fastcore

CVE-2026-65320-fastcore

Documents CVE-2026-65320, a tar-slip path traversal in fastcore's untar_dir(), with a harmless proof-of-concept demonstrating arbitrary file write and code execution.

View Repository
1 day agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-65320: Path Traversal (Tar Slip) in fastcore via untar_dir()

Severity: Critical, 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

Affected: fastcore <= 2.2.30

Fixed in: Not fixed at time of writing

CWE: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory, 'Path Traversal')

Component: fastcore.xtras.untar_dir() → fastcore.xtras._unpack() → shutil.unpack_archive()

High-risk runtime: Python < 3.14 (Python 3.14 makes the safe data tar filter the default)

Reported by: Rahul Karne

CNA: VulnCheck


Summary

fastcore.xtras.untar_dir(fname, dest) is a documented helper that untars an archive "into dest".

Internally, it hands the archive to the standard library's shutil.unpack_archive() without an extraction filter, without validating archive member paths, and without any post-extraction containment check.

As a result, a TAR archive whose members contain ../ traversal sequences or absolute paths can write files outside the directory the caller asked fastcore to extract into.

A caller who reasonably expects untar_dir(fname, dest) to confine everything to dest instead gets arbitrary file write anywhere the process can write.


Impact

Arbitrary file write under the authority of the process calling untar_dir().

Depending on what is overwritten, this can result in:

  • Code execution — overwrite a Python file that the application later imports, such as a plugin, startup hook, or importable module, or drop a file into an auto-loaded location.
  • Data / configuration tampering — overwrite configuration files, credentials, or application data.
  • Denial of service — corrupt files the service depends on.

The proof of concept demonstrates the full write → import → code-execution chain end to end, entirely inside a harmless demo directory.


Reach

fastcore is a foundational dependency across the fast.ai ecosystem, including:

  • fastai
  • nbdev
  • ghapi
  • Other related packages

It receives tens of millions of downloads per month.

untar_dir() is the extraction primitive behind the common "download an archive, then unpack it" workflow, which follows the same general pattern as fastai's untar_data.

Any code path that feeds untar_dir() an archive whose contents are not fully trusted is exposed.


Technical Detail

The vulnerable code exists in fastcore/xtras.py:

root@kitploit:~
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() creates an internal temporary extraction directory:

root@kitploit:~
<tempdir>/<random>/<archive-stem>/

It then calls _unpack(), which forwards the archive directly to:

root@kitploit:~
shutil.unpack_archive()

For TAR archives, this ultimately calls tarfile.extractall().

On Python < 3.14, the default extraction behavior is fully_trusted, meaning traversal members can be honored.

For example, an archive member such as:

root@kitploit:~
../../../some/other/dir/file

is written relative to the extraction directory and can therefore escape it.

Nothing in fastcore:

  • Passes filter="data" where supported.
  • Rejects absolute paths.
  • Rejects drive-letter paths.
  • Rejects UNC paths.
  • Rejects .. path components.
  • Rejects symlink or hardlink members.
  • Verifies that every extracted path remained under the intended extraction root before returning success.

Root Cause

untar_dir() treats shutil.unpack_archive() as though it were a safe, sandboxed archive extractor.

It is not.

Python's standard library documentation warns that extracting untrusted archives may create files outside the requested destination and recommends safe extraction filtering for TAR archives.

fastcore neither passes an appropriate extraction filter nor implements an equivalent containment guard for the Python versions it supports.

It also does not warn callers of untar_dir() about this security-sensitive behavior.


Why the TAR Path Specifically

TAR members can contain arbitrary path strings.

On affected Python versions, tarfile.extractall() does not automatically neutralize .. traversal sequences by default.

Writing a traversal member relative to fastcore's temporary extraction directory is therefore sufficient to escape that directory and write anywhere the process has permission to write.

A reliable primitive is relative traversal such as:

root@kitploit:~
../../../target/file

This is the technique used by the proof of concept.


Delivery Over the Network

The dangerous input is the archive contents, not the destination path chosen by the developer.

Archives are frequently obtained from external or semi-trusted locations, including:

  • Model bundles
  • Dataset archives
  • Plugin bundles
  • CI/CD artifacts
  • User uploads
  • Partner uploads
  • Remote HTTP downloads

Any service or tool that downloads an archive from an untrusted or semi-trusted source and subsequently processes it using untar_dir() may therefore be reachable.

The PoC also includes a variant that serves the crafted archive from an attacker-controlled HTTP endpoint to demonstrate this delivery path.


Exploitation Preconditions

Successful exploitation requires:

  1. The application calls fastcore.xtras.untar_dir() on an archive whose contents are attacker-influenced, such as an uploaded, downloaded, or otherwise untrusted archive.

  2. The runtime uses Python < 3.14, or another configuration where a safe TAR extraction filter is not enforced.

  3. For escalation from arbitrary file write to code execution, the process later imports or loads a file from a location reachable by the traversal, such as:

    • A plugin directory
    • An importable Python module
    • A startup hook
    • Another auto-loaded file location

Arbitrary file write and configuration/data modification require only conditions 1 and 2.


Proof of Concept

poc_fastcore_cna_demo.py invokes the real fastcore.xtras.untar_dir() API.

The demonstration is intentionally harmless.

Every file created by the PoC remains inside a single demo directory specified using:

root@kitploit:~
--demo-root

The PoC does not modify real system files and does not access cloud services or credentials.

What the PoC Does

  1. Prints the environment details and vulnerable source code for _unpack() and untar_dir().

  2. Creates a demonstration layout containing:

    • An intended extraction root
    • A separate application directory:
      root@kitploit:~
      service_app/plugins/
      
  3. Creates:

root@kitploit:~
attacker_supplied_upload.tar

containing archive members designed to point outside the intended extraction root, including traversal members and:

root@kitploit:~
service_app/plugins/startup_hook.py
  1. Calls a simulated upload handler:
root@kitploit:~
def auto_extract_uploaded_archive(received_archive):
    return untar_dir(
        received_archive,
        intended_root,
        overwrite=True
    )
  1. Verifies that files were written outside the intended extraction directory.

  2. Simulates a service reload by importing the archive-written:

root@kitploit:~
startup_hook.py

The harmless startup hook creates:

root@kitploit:~
SERVICE_RELOAD_MARKER

This demonstrates the complete chain:

root@kitploit:~
Attacker-controlled archive
        ↓
Path traversal during extraction
        ↓
Arbitrary file write
        ↓
Write into importable / auto-loaded location
        ↓
Application loads attacker-controlled file
        ↓
Code execution

Setup

Install the affected package:

root@kitploit:~
pip install fastcore

The issue has been confirmed through:

root@kitploit:~
fastcore 2.2.30

The demonstration can run against either:

  • A pip-installed copy of fastcore
  • A locally extracted source tree selected using --source

All PoC writes remain inside the directory specified through --demo-root.


Run

Clean any previous PoC output:

root@kitploit:~
python poc_fastcore_cna_demo.py --demo-root ./poc_fastcore --clean

Run the demonstration:

root@kitploit:~
python poc_fastcore_cna_demo.py \
  --demo-root ./poc_fastcore \
  --source latest \
  --no-pause

Expected Output

Example abridged output:

root@kitploit:~
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.

Remediation

For fastcore Maintainers

1. Use Safe TAR Extraction Filtering

On supported Python versions, use a safe extraction filter such as:

root@kitploit:~
filter="data"

with shutil.unpack_archive() or the corresponding tarfile extraction operation.


2. Validate Archive Members Before Extraction

Every archive member should be checked before extraction.

Reject:

  • Absolute paths
  • Windows drive-letter paths
  • UNC paths
  • Paths containing ..
  • Unsafe symbolic links
  • Unsafe hard links

Link targets should also be resolved and validated before extraction.


3. Enforce Extraction Containment

Resolve every destination path before writing and verify that it remains beneath the intended extraction root.

Conceptually:

root@kitploit:~
resolved_member_path
        ↓
must remain inside
        ↓
resolved_extraction_root

Extraction should fail if the resolved destination escapes the extraction root.


4. Add Regression Tests

Regression tests should cover at least:

root@kitploit:~
../ traversal
absolute paths
Windows drive-letter paths
UNC paths
symbolic links
hard links

5. Document Security Expectations

Clearly document whether untar_dir() is intended to safely process untrusted archives.

If unsafe extraction is intentionally supported, the secure behavior should still be the default.

Unsafe behavior should require explicit opt-in rather than silently trusting archive contents.


Temporary Guidance for Users

Until a package-level fix is released:

  • Prefer Python 3.14+ where applicable.
  • Do not pass untrusted archives directly to untar_dir().
  • Validate all archive members before extraction.
  • Ensure extracted paths cannot escape the intended destination directory.
  • Treat remotely downloaded or user-supplied archives as attacker-controlled input.

CVSS Considerations

The underlying technical defect is an arbitrary file-write vulnerability caused by archive path traversal.

However, the final severity depends on the deployment environment and how untar_dir() is exposed.

Network-Facing Service Scenario

A representative vector may approach:

root@kitploit:~
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Result:

root@kitploit:~
9.8 — Critical

Developer / CLI Scenario

If exploitation instead requires a developer to manually download and extract an archive, user interaction and attack complexity may be higher.

The resulting CVSS score would therefore be materially lower.


Caveats

Two important factors should be considered when evaluating the issue.

Existing Vulnerability Class

This is an instance of the long-known unsafe TAR extraction vulnerability class associated with:

root@kitploit:~
CVE-2007-4559

Modern Python releases have introduced safer archive extraction behavior.

Python 3.14 makes the safe data extraction filter the default.

Therefore, the primary affected environment is Python < 3.14.

However, those runtimes remain widely deployed.

Untrusted Archive Requirement

The vulnerability becomes exploitable when a caller supplies untar_dir() with an archive whose contents are attacker-controlled or otherwise untrusted.

This report therefore treats the contents of the archive as the untrusted security boundary.

A robust archive extraction helper should fail safely regardless of how the archive was obtained.


Disclosure Timeline

Replace the placeholder dates below with the actual disclosure dates.

  • YYYY-MM-DD — Vulnerability reported to the maintainers.
  • YYYY-MM-DD — Vendor response / acknowledgment / no response.
  • 2026-09-26 — Confirmed still unfixed in the latest release (2.2.30); extraction code remained unchanged.

Credit

Discovered and reported by Rahul Karne.


References

  • fastcore untar_dir() documentation
    https://fastcore.fast.ai/xtras.html

  • fastcore xtras.py source
    https://github.com/AnswerDotAI/fastcore/blob/main/fastcore/xtras.py

  • fastcore on PyPI
    https://pypi.org/project/fastcore/

  • Python shutil.unpack_archive() documentation
    https://docs.python.org/3/library/shutil.html#shutil.unpack_archive

  • Python tarfile extraction filters
    https://docs.python.org/3/library/tarfile.html#extraction-filters

  • PEP 706 — Filter for tarfile.extractall
    https://peps.python.org/pep-0706/

  • CWE-22 — Improper Limitation of a Pathname to a Restricted Directory
    https://cwe.mitre.org/data/definitions/22.html

  • CVE-2007-4559 — Unsafe TAR extraction vulnerability class
    https://nvd.nist.gov/vuln/detail/CVE-2007-4559


About

This repository documents a coordinated-disclosure security finding and provides a harmless, self-contained proof of concept.

The PoC writes only inside the --demo-root directory specified by the user and performs no destructive actions.

Any network functionality included in the demonstration is limited to an optional local demonstration.

This material is provided for defensive security research and educational purposes.


Press

Media inquiries: [email protected]. Full PoC (attacker server, traversal archive, victim application) and additional technical detail available on request.

Download Tool