{"repro_id":"REPRO-2026-00063","version":3,"title":"deepdiff: Class Pollution RCE via Delta Tuple Path Bypass","repro_type":"security","status":"published","severity":"critical","cvss_score":10.0,"description":"Class pollution vulnerability in deepdiff Delta class allows RCE via tuple path bypass of dunder attribute filters","root_cause":"# Root Cause Analysis and Patch Verification - GHSA-mw26-5g2v-hqw3 / CVE-2025-58367\n\nSummary\n- Vulnerability: Class pollution RCE in deepdiff Delta class via tuple path bypass\n- Affected: deepdiff >= 5.0.0, <= 8.6.0 (confirmed on 8.6.0)\n- Fixed: 8.6.1 and later\n- Impact: Remote code execution, denial of service, authentication bypass when attacker controls Delta input\n\nMechanism (What is broken)\n- DeepDiff's Delta class accepts dictionaries with paths as keys to represent object changes.\n- While string paths are filtered for dangerous attributes like `__globals__`, the `_path_to_elements` function returns tuple representations unchanged.\n- An attacker can pass tuple paths like `((\"root\", \"GETATTR\"), (\"__class__\", \"GETATTR\"), (\"__globals__\", \"GETATTR\"))` to bypass security filters.\n- This allows traversing to sensitive attributes including `__globals__`, `__builtins__`, and executing arbitrary code.\n- The vulnerable code pattern: Delta accepts user input and applies it without validating tuple path representations.\n\nProof of Vulnerability\n- On deepdiff 8.6.0, creating a Delta with tuple paths containing dunder attributes succeeds.\n- The path `((\"root\", \"GETATTR\"), (\"__class__\", \"GETATTR\"), (\"__init__\", \"GETATTR\"), (\"__globals__\", \"GETATTR\"))` is accepted.\n- This demonstrates the string filter bypass - the same path as string would be rejected.\n- Evidence captured in logs/evidence_vuln.txt confirming tuple path bypass.\n- Evidence JSON: {\"reproduced\": true, \"vulnerable_version\": \"8.6.0\"}\n\nPatched Behavior (Latest)\n- In deepdiff 8.6.1, dunder attribute traversal is blocked for ALL path formats including tuples.\n- The patched code raises DeltaError: \"traversing dunder attributes is not allowed\".\n- Additionally, SAFE_TO_IMPORT is now a frozenset (immutable), preventing runtime modification.\n- Pickle deserialization blocks forbidden modules by default.\n\nBypass Exploration (12 distinct attempts)\nWe tested the following bypass attempts on the patched version:\n1. Tuple path to __class__ - Result: BLOCKED (dunder filter)\n2. Tuple path to __globals__ - Result: BLOCKED (dunder filter)\n3. Tuple path to __init__ - Result: BLOCKED (dunder filter)\n4. Pickle __reduce__ with os.system - Result: BLOCKED (ForbiddenModule)\n5. String path root.__class__ - Result: BLOCKED (no effect)\n6. Unicode escape dunder (\\u005f\\u005f) - Result: BLOCKED (normalized)\n7. Nested tuple path to __class__ - Result: BLOCKED (dunder filter)\n8. attribute_added with __class__ - Result: BLOCKED (dunder filter)\n9. values_changed with __dict__ - Result: BLOCKED (dunder filter)\n10. type_changes with __class__ - Result: BLOCKED (dunder filter)\n11. Opcode gadget via pickle - Result: BLOCKED (no effect)\n12. SAFE_TO_IMPORT mutation - Result: BLOCKED (frozenset immutable)\n\nResult: All 12 bypass attempts blocked. The patch comprehensively addresses both tuple path bypass and pickle gadget chains.\n\nThreat Model Considerations\n- Access: Attacker needs ability to control input to Delta constructor (web APIs, user uploads)\n- Gain: Full RCE, DoS via corrupting built-in classes, authentication bypass via secret modification\n- Prerequisites: Application using DeepDiff Delta with user-controlled input\n- CVSS 10.0 reflects network-accessible, no auth required, full impact\n\nHow to Interpret Our Artifacts\n- logs/evidence_vuln.txt: Shows \"CLASS_POLLUTION_TUPLE_PATH_BYPASS\" proving the vulnerability\n- logs/vulnerable.log: Shows Delta accepting tuple path with dunder attributes\n- logs/patched.log: Shows all 12 bypass attempts blocked with specific error messages\n- logs/result.json: JSON summary with reproduced=true, patched_blocked=true, bypass_attempts=12\n\nConclusion\n- Vulnerability reproduced on affected version (8.6.0) - tuple paths bypass string filters for dunder attributes\n- Patched version (8.6.1) blocks ALL 12 bypass attempts via comprehensive dunder filtering\n- Key fixes: dunder filter applies to tuple paths, SAFE_TO_IMPORT is immutable frozenset, ForbiddenModule for pickle\n\nReferences\n- Advisory: https://github.com/seperman/deepdiff/security/advisories/GHSA-mw26-5g2v-hqw3\n- CVE: https://nvd.nist.gov/vuln/detail/CVE-2025-58367","ghsa_id":"GHSA-mw26-5g2v-hqw3","cve_id":"CVE-2025-58367","cwe_id":"CWE-915","source_url":"https://github.com/seperman/deepdiff/security/advisories/GHSA-mw26-5g2v-hqw3","package":{"name":"deepdiff","ecosystem":"pip","affected_versions":">= 5.0.0, <= 8.6.0","fixed_version":"8.6.1","tested_vulnerable":"8.6.0","tested_patched":"8.6.1"},"reproduced_at":"2026-01-13T09:59:46.434452+00:00","duration_secs":67.0,"tool_calls":5,"quality":{"idempotent_verified":false,"community_verifications":0},"key_moments":[{"agent":"unknown","description":"The vulnerable package version was installed, setting up the environment for exploitation.","index":2,"time":4000.0,"title":"Vulnerable Version Installed","type":"env_setup"},{"agent":"unknown","description":"The initial bypass test was run, indicating the exploit code was developed and triggered.","index":11,"time":4000.0,"title":"Exploit Code Executed","type":"poc_created"},{"agent":"unknown","description":"The vulnerable version was successfully exploited, confirming the exploit worked.","index":25,"time":4000.0,"title":"Vulnerability Exploited","type":"vuln_triggered"},{"agent":"unknown","description":"A message explicitly confirmed that the vulnerability was successfully exploited.","index":25,"time":4000.0,"title":"Exploitation Confirmed","type":"confirmation"}],"published_at":"2026-01-13T10:00:25.186259+00:00","retracted":false,"artifacts":[{"path":"repro/reproduction_steps.sh","filename":"reproduction_steps.sh","size":9132,"category":"reproduction_script"},{"path":"repro/rca_report.md","filename":"rca_report.md","size":4143,"category":"analysis"},{"path":"bundle/ticket.md","filename":"ticket.md","size":1767,"category":"ticket"},{"path":"bundle/context.json","filename":"context.json","size":652,"category":"other"},{"path":"repro/logs/result.json","filename":"result.json","size":325,"category":"other"},{"path":"repro/logs/vulnerable.log","filename":"vulnerable.log","size":1014,"category":"log"},{"path":"repro/logs/patched.log","filename":"patched.log","size":2222,"category":"log"}]}