Using jsonpickle.decode() with Untrusted Data
Decoding JSON from user requests, external APIs, or uploaded files using jsonpickle.
jsonpickle deserialization vulnerabilities occur when jsonpickle.decode() processes untrusted data. Unlike standard JSON, jsonpickle preserves Python object types and can reconstruct complex objects including invoking constructors and __reduce__ methods. Attackers can craft malicious payloads that execute arbitrary code during deserialization.
import jsonpickle
from flask import Flask, request, jsonify
app = Flask(__name__)
# VULNERABLE: jsonpickle can execute arbitrary code
@app.route('/api/data/import', methods=['POST'])
def import_data():
data = request.get_json()
# DANGEROUS: jsonpickle.decode can execute code
obj = jsonpickle.decode(data['payload'])
if hasattr(obj, 'process'):
result = obj.process()
return jsonify({'status': 'success', 'result': result})
return jsonify({'status': 'success', 'data': str(obj)})
# Malicious payload:
# {
# "py/object": "__main__.MaliciousClass",
# "py/reduce": [
# {"py/function": "os.system"},
# {"py/tuple": ["rm -rf /"]}
# ]
# }import json
from flask import Flask, request, jsonify
from pydantic import BaseModel, ValidationError
app = Flask(__name__)
# Define explicit data models
class UserData(BaseModel):
name: str
email: str
preferences: dict
class Config:
extra = 'forbid' # Reject unknown fields
# SECURE: use standard JSON with validation
@app.route('/api/data/import', methods=['POST'])
def import_data():
try:
data = request.get_json()
# SAFE: standard JSON parsing
raw_data = data['payload']
# Validate against schema
user_data = UserData(**raw_data)
result = process_user_data(user_data)
return jsonify({'status': 'success', 'result': result})
except ValidationError as e:
return jsonify({'error': 'Invalid data', 'details': e.errors()}), 400
except Exception as e:
return jsonify({'error': 'Processing failed'}), 500
def process_user_data(user_data: UserData) -> str:
return f"Processed user: {user_data.name}"The vulnerable code uses jsonpickle.decode() which can reconstruct arbitrary Python objects and execute code through constructors or __reduce__ methods. The secure version uses standard json parsing with Pydantic validation to ensure data conforms to expected schemas without object reconstruction.
Decoding JSON from user requests, external APIs, or uploaded files using jsonpickle.
Sourcery automatically identifies remote code execution via jsonpickle deserialization and many other security issues in your codebase.