CVE-2025-14931
Hugging Face smolagents allows unauthenticated RCE via pickle deserialization.
- CVSS 10.0
- CWE-502
- Input Validation and Sanitization
- Remote
Hugging Face smolagents Remote Python Executor Deserialization of Untrusted Data Remote Code Execution Vulnerability. This vulnerability allows remote attackers to execute arbitrary code on affected installations of Hugging Face smolagents. Authentication is not required to exploit this vulnerability. The specific flaw exists within the parsing of pickle data. The issue results from the lack of proper validation of user-supplied data, which can result in deserialization of untrusted data. An attacker can leverage this vulnerability to execute code in the context of the service account. Was ZDI-CAN-28312.
- CWE
- CWE-502
- CVSS base score
- 10.0
- Published
- 2025-12-23
- OWASP
- A08 Software and Data Integrity Failures
- Orthogonal defect classification
- Timing/Serialization
- Code defect classification
- Serialization Issues
- Category
- Input Validation and Sanitization
- Subcategory
- Insecure Parsing or Deserialization
- Accessibility scope
- Remote
- Impact
- Arbitrary Code Execution
- Affected component
- Hugging Face
- Fixed by upgrading
- Yes
Solution
Upgrade to smol-agents version 0.1.3 or later.
Vulnerable code sample
import pickle
from flask import Flask, request
app = Flask(__name__)
@app.route('/process_data', methods=['POST'])
def process_data():
# This endpoint receives serialized data objects for processing.
raw_data = request.data
# The data is deserialized to be used by the application.
data_object = pickle.loads(raw_data)
# Further processing on the data_object would happen here.
print(f"Processing object of type {type(data_object)}")
return "Success", 200
if __name__ == '__main__':
# Start the server to listen for incoming data.
app.run(host='0.0.0.0', port=1337)Patched code sample
import json
def safe_process_data(data: bytes):
"""
Represents the fixed code for a deserialization vulnerability like CVE-2025-14931.
This function safely deserializes user-supplied data by using the JSON
format, which is designed for data interchange and cannot execute arbitrary code.
It replaces a hypothetical insecure implementation that would have used `pickle.load()`
or `pickle.loads()` on untrusted data.
Args:
data: A byte string containing serialized data from an untrusted source.
Returns:
The deserialized Python object (e.g., a dict or list) if the data is
valid JSON, otherwise None.
"""
try:
# The core of the fix is to switch from a dangerous deserializer like
# pickle to a safe, data-only format like JSON.
# 1. Decode the byte string into a standard string format (e.g., UTF-8).
# This is a necessary step before parsing with the json module.
data_str = data.decode('utf-8')
# 2. Use json.loads() to parse the data. This function only builds
# Python objects like dicts, lists, strings, and numbers. It will
# not execute any functions or code embedded in the data stream,
# which is what makes pickle dangerous with untrusted input.
deserialized_object = json.loads(data_str)
# 3. (Optional but recommended) Further validation can be performed here
# on the structure and content of `deserialized_object` to ensure it
# conforms to the application's expectations before it is used.
return deserialized_object
except (json.JSONDecodeError, UnicodeDecodeError):
# If the data is not valid JSON or cannot be decoded (e.g., it's a
# malicious pickle stream), it is safely rejected by catching the
# exception. This provides the "proper validation of user-supplied data"
# that was missing in the vulnerable version.
return None
except Exception:
# Catch any other unexpected errors during processing for robustness.
return NonePayload
import pickle
import os
class RCE:
def __reduce__(self):
cmd = 'id'
return os.system, (cmd,)
print(pickle.dumps(RCE()))
Cite this entry
@misc{vaitp:cve202514931,
title = {{Hugging Face smolagents allows unauthenticated RCE via pickle deserialization.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2025},
note = {VAITP Python Vulnerability Dataset, entry CVE-2025-14931},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-14931/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
