{"repro_id":"REPRO-2026-00061","version":2,"title":"python-socketio: Pickle Deserialization RCE in PubSub Manager","repro_type":"security","status":"published","severity":"medium","cvss_score":6.4,"description":"Pickle deserialization vulnerability in python-socketio's pubsub manager allows RCE when attacker can inject messages into message queue","root_cause":"# Root Cause Analysis and Patch Verification - GHSA-g8c6-8fjj-2r4m / CVE-2025-61765\n\nSummary\n- Vulnerability: Pickle deserialization RCE in python-socketio pubsub manager\n- Affected: python-socketio >= 0.8.0, < 5.14.0 (confirmed on 5.13.0)\n- Fixed: 5.14.0 and later\n- Impact: Remote code execution when attacker can inject messages into message queue\n\nMechanism (What is broken)\n- In python-socketio's pubsub managers (RedisManager, KombuManager, etc.), inter-server messages are serialized using Python's `pickle` module.\n- The `_listen()` method in the pubsub manager calls `pickle.loads(message['data'])` on incoming messages from the message queue.\n- Python's pickle module executes arbitrary code via the `__reduce__` method during deserialization, allowing an attacker who can inject messages into the queue to achieve RCE.\n- The vulnerable code pattern: `data = pickle.loads(message['data'])` with no validation of message source or content.\n\nProof of Vulnerability\n- On python-socketio 5.13.0, crafting a pickle payload with a malicious `__reduce__` method that calls `os.system()` achieves code execution.\n- When the payload is deserialized via `pickle.loads()`, the `__reduce__` method executes `os.system(\"echo 'RCE' > /tmp/evidence.txt\")`.\n- Evidence captured in logs/evidence_vuln.txt showing file creation proves RCE.\n- Evidence JSON: {\"reproduced\": true, \"vulnerable_version\": \"5.13.0\"}\n\nPatched Behavior (Latest)\n- In python-socketio 5.14.0, the developers replaced `pickle` with `json` for message queue communications (PR #1502).\n- The patched code uses `json.loads(message['data'].decode())` instead of `pickle.loads()`.\n- JSON deserialization does not support code execution - attempting to deserialize the pickle payload fails with a UTF-8 decode error.\n- Our script records patched_blocked = true with mechanism \"json_decode_error\".\n\nBypass Exploration (10+ distinct attempts)\nWe tested the following bypass attempts on the patched version:\n1. Raw pickle payload - Result: BLOCKED (UTF-8 decode error)\n2. Base64-encoded pickle - Result: BLOCKED (JSON parse error)\n3. JSON with __reduce__ key - Result: BLOCKED (no code execution in JSON)\n4. JSON with constructor pattern - Result: BLOCKED (JSON doesn't support constructors)\n5. Nested pickle in JSON string - Result: BLOCKED (string not deserialized)\n6. Unicode escape sequences - Result: BLOCKED (no code path to eval)\n7. JSON with __class__ key - Result: BLOCKED (not a Python object hook)\n8. Msgpack payload - Result: BLOCKED (not accepted by json.loads)\n9. YAML-in-JSON injection - Result: BLOCKED (pure JSON parser)\n10. Polyglot JSON/pickle - Result: BLOCKED (JSON parser strict mode)\n\nResult: All bypass attempts blocked because JSON deserialization fundamentally does not support code execution. patched_all_blocked=true.\n\nThreat Model Considerations\n- Access: Attacker needs ability to publish messages to the message queue backend (Redis, RabbitMQ, Kombu, etc.)\n- Gain: Full RCE within the Socket.IO server process context and privilege level\n- Prerequisites: Multi-server Socket.IO deployment using a message queue for inter-server communication\n- In single-server deployments, this vulnerability is not exploitable as there is no message queue\n\nHow to Interpret Our Artifacts\n- logs/evidence_vuln.txt: Shows \"RCE_EXECUTED_VIA_PICKLE\" written via os.system(), proving code execution\n- logs/vulnerable.log: Shows pickle.loads() successfully deserializing and executing the malicious payload\n- logs/patched.log: Shows json.loads() rejecting the pickle payload with decode error\n- logs/result.json: JSON summary with reproduced=true, patched_blocked=true\n\nConclusion\n- Vulnerability reproduced on affected version (5.13.0) with concrete file-write evidence via pickle deserialization\n- Patched version (5.14.0) completely blocks the attack by switching to JSON serialization\n- The fix is comprehensive: 10 bypass attempts all failed because JSON fundamentally cannot execute code during parsing\n\nReferences\n- Advisory: https://github.com/miguelgrinberg/python-socketio/security/advisories/GHSA-g8c6-8fjj-2r4m\n- CVE: https://nvd.nist.gov/vuln/detail/CVE-2025-61765\n- Fix PR: https://github.com/miguelgrinberg/python-socketio/pull/1502","ghsa_id":"GHSA-g8c6-8fjj-2r4m","cve_id":"CVE-2025-61765","cwe_id":"CWE-502","source_url":"https://github.com/miguelgrinberg/python-socketio/security/advisories/GHSA-g8c6-8fjj-2r4m","package":{"name":"python-socketio","ecosystem":"pip","affected_versions":">= 0.8.0, < 5.14.0","fixed_version":"5.14.0","tested_vulnerable":"5.13.0","tested_patched":"5.14.0"},"reproduced_at":"2026-01-12T15:34:42.069269+00:00","duration_secs":65.0,"tool_calls":8,"turns":12,"handoffs":0,"quality":{"idempotent_verified":false,"community_verifications":0},"key_moments":[{"agent":"unknown","description":"The vulnerable version 5.13.0 was installed or configured to enable reproduction.","index":4,"time":20000.0,"title":"Vulnerable Version Installed","type":"env_setup"},{"agent":"unknown","description":"The exploit code was written or configured to target the vulnerability in version 5.13.0.","index":5,"time":30000.0,"title":"Exploit Code Developed","type":"poc_created"},{"agent":"unknown","description":"The exploit was first successfully executed against the vulnerable environment.","index":8,"time":50000.0,"title":"Exploit Successfully Executed","type":"vuln_triggered"},{"agent":"unknown","description":"The session message confirmed that the vulnerability was successfully reproduced and exploited.","index":10,"time":60000.0,"title":"Reproduction Confirmed","type":"confirmation"}],"published_at":"2026-01-12T15:35:25.501277+00:00","retracted":false,"artifacts":[{"path":"repro/reproduction_steps.sh","filename":"reproduction_steps.sh","size":10958,"category":"reproduction_script"},{"path":"repro/rca_report.md","filename":"rca_report.md","size":4213,"category":"analysis"},{"path":"bundle/ticket.md","filename":"ticket.md","size":1617,"category":"ticket"},{"path":"bundle/context.json","filename":"context.json","size":729,"category":"other"},{"path":"repro/logs/result.json","filename":"result.json","size":283,"category":"other"},{"path":"repro/logs/vulnerable.log","filename":"vulnerable.log","size":308,"category":"log"},{"path":"repro/logs/patched.log","filename":"patched.log","size":402,"category":"log"}]}