CVE-2026-48207: Critical Deserialization Bypass in Apache Fury PyFury
A critical deserialization vulnerability has been disclosed in Apache Fury's Python implementation (PyFury), tracked as CVE-2026-48207 (CVSS 9.8, Critical). The flaw allows attackers to bypass documented DeserializationPolicy validation hooks during reduce-state restoration and global-name resolution via PyFury's ReduceSerializer — enabling arbitrary remote code execution when an application deserializes attacker-controlled data.
Vulnerability Overview
| Attribute | Value |
|---|---|
| CVE ID | CVE-2026-48207 |
| CVSS Score | 9.8 (Critical) |
| CWE Classification | CWE-502 — Deserialization of Untrusted Data |
| Affected Component | Apache Fury — PyFury (Python library) |
| Attack Vector | Network (unauthenticated if app exposes deserialization endpoint) |
| Authentication Required | Depends on application exposure |
| Impact | Arbitrary Code Execution |
| Published | 2026-05-21 |
| Source | NIST NVD |
Background: Apache Fury and PyFury
Apache Fury is a high-performance cross-language serialization framework designed as a fast alternative to JSON and Protocol Buffers. It supports Java, Python, Go, JavaScript, and Rust, and is used in performance-critical data exchange scenarios — including distributed systems, ML pipelines, and microservice communications.
PyFury is the Python implementation of the framework. It provides DeserializationPolicy as a documented security mechanism to restrict which classes can be deserialized — the intended protection against unsafe deserialization attacks.
Technical Analysis
The Vulnerability
CVE-2026-48207 arises because PyFury's ReduceSerializer — the component responsible for handling Python objects that implement the __reduce__ protocol — bypasses DeserializationPolicy validation during two specific operations:
- Reduce-state restoration: When restoring an object's state via
__reduce__, the serializer does not invoke the configured policy hooks to validate whether the target class is permitted - Global-name resolution: When resolving class names to Python objects during deserialization, the serializer skips policy validation
This creates a gap where an attacker-controlled serialized payload can reference and instantiate arbitrary Python classes — even those explicitly blocked by the application's DeserializationPolicy — by routing execution through the ReduceSerializer path.
The reduce Protocol and RCE
Python's __reduce__ protocol allows objects to define custom serialization behavior. When exploited, a malicious __reduce__ implementation can call arbitrary Python functions during deserialization — achieving Remote Code Execution without any additional steps.
The ReduceSerializer in PyFury uses this protocol internally to handle complex object graphs. CVE-2026-48207 means the security policy that should gate which objects can go through this path is not enforced, allowing an attacker to craft a payload that triggers code execution on the server.
Policy Bypass Mechanism
Normal deserialization path:
Input data → class lookup → DeserializationPolicy.check() → instantiate
Vulnerable ReduceSerializer path:
Input data → ReduceSerializer.__reduce__ → instantiate [POLICY BYPASS]
PyFury's DeserializationPolicy was intended to prevent exactly this scenario by whitelisting or blacklisting specific classes. The flaw is that this policy is not enforced in the ReduceSerializer code path.
Affected Applications
An application is vulnerable if it:
- Uses PyFury to deserialize data
- Deserializes data from an untrusted or attacker-influenced source (API input, message queue, file upload, network socket)
- Relies on
DeserializationPolicyas a security control — believing it will prevent unauthorized class instantiation
Applications that never deserialize externally-provided data are not directly at risk, but the policy bypass undermines the documented security guarantees of the library.
Remediation
1. Update PyFury
Monitor the Apache Fury releases page for a patched version addressing CVE-2026-48207. Apply any available patch immediately.
# Update Apache Fury via pip
pip install --upgrade apache-fury
# Verify installed version
pip show apache-fury2. Architectural Mitigations (Until Patched)
If a patch is not yet available, apply defense-in-depth measures:
Use cryptographic signatures on serialized data to prevent tampered payloads from reaching the deserializer:
import hmac
import hashlib
def verify_payload(data: bytes, signature: str, secret: bytes) -> bool:
expected = hmac.new(secret, data, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
# Only deserialize after successful signature verification
if not verify_payload(raw_data, received_sig, APP_SECRET):
raise ValueError("Payload signature invalid — rejecting deserialization")Isolate deserialization processes:
# Run deserialization in a restricted subprocess or container
# with limited filesystem, network, and syscall access
# Consider seccomp profiles, namespaces, or dedicated microservicesReplace PyFury with schema-validated formats for untrusted input:
# For untrusted input, prefer schema-validated formats
import json
import jsonschema # enforce strict schema validation
# Use JSON + schema validation for any externally-sourced data
# Avoid binary deserialization formats with untrusted data until patched3. Detection
Monitor for signs of deserialization exploitation:
# Watch for unexpected child processes spawned by your Python application
# (common indicator of __reduce__ RCE payloads)
# auditd rule: -a always,exit -F arch=b64 -S execve -F ppid=<app_pid>
# Monitor for unusual outbound network connections
ss -tnp | grep <app_process_name>
# Check for unexpected files in writable locations
ls -la /tmp/Impact Assessment
| Impact Area | Risk |
|---|---|
| Remote Code Execution | Full application server compromise |
| Data Exfiltration | All accessible data, credentials, secrets |
| Lateral Movement | Attacker can pivot to internal network |
| Persistence | Can install backdoors, SSH keys, scheduled tasks |
| Supply Chain | If used in build pipelines, compromise propagates |
The CVSS 9.8 score reflects the critical nature of unauthenticated RCE when an application exposes a PyFury deserialization endpoint to untrusted input.
Key Takeaways
- CVE-2026-48207 allows
DeserializationPolicybypass in Apache Fury's PyFury via theReduceSerializerpath - CVSS 9.8 (Critical) — arbitrary code execution possible when deserializing attacker-controlled data
- Immediate action: Update PyFury to a patched version; do not deserialize untrusted data with affected versions
- Defense-in-depth: Use HMAC-signed payloads, process isolation, and network segmentation around deserialization services
- Monitor for unexpected child processes spawned by Python application servers