| Titolo | Yue Zhao / yzhao062 pyod 3.5.0 through 3.5.2 CWE-502: Deserialization of Untrusted Data |
|---|
| Descrizione | A vulnerability was found in pyod 3.5.0 through 3.5.2 and classified
as high severity in deployments that load untrusted model artifacts.
Affected is the model persistence component, specifically
pyod.utils.persistence.load().
The function calls joblib.load(path) before checking whether the loaded
object is a PyOD persistence envelope. Since joblib uses pickle-based
deserialization, a crafted artifact can execute Python reducer payloads
during loading. The subsequent _is_envelope(), schema-version,
dependency-version, and strict=True checks happen only after the object
has already been unpickled.
This is not a default network-exposed vulnerability in the PyOD library
itself. Exploitation requires an application or user to load a malicious
artifact. The attack becomes remotely reachable when a downstream system
accepts uploaded model files, imports artifacts from external model
registries, loads CI artifacts, or otherwise lets an attacker influence
the file passed to pyod.utils.persistence.load().
Authentication required: contextual. For a local malicious file attack,
no application authentication is required but user interaction is
required. For hosted ML platforms, the attacker may need low privileges
such as permission to upload or register a model artifact.
User interaction required: yes for local/manual loading; no when a
service automatically loads attacker-supplied artifacts.
Technical Details
- Affected file/function: pyod/utils/persistence.py, load()
- Vulnerable parameter: path
- Attack vector: Local by default; Network in applications exposing model upload/import workflows
- Privileges required: None for a malicious local artifact loaded by a user; Low for authenticated model upload workflows
- Trigger condition: A victim process calls pyod.utils.persistence.load() on a crafted joblib/pickle artifact
Relevant Code Flow
- load() calls joblib.load(path) first.
- The returned object is then passed to _handle_loaded_object().
- _handle_loaded_object() calls _is_envelope(obj).
- Schema, dependency drift, and strict-mode validation are performed after deserialization.
Proof of Concept Summary
A local proof of concept used a top-level dictionary containing the
expected envelope keys, including _pyod_persistence_version and model.
The model value was an object whose pickle reducer wrote a harmless
marker file during deserialization. Calling load(path, strict=True)
created the marker file before validation completed, demonstrating that
strict mode and envelope validation do not prevent reducer execution.
Observed output:
pre_dump_is_envelope: True
marker_after_dump: False
load_result: 0
marker_after_load: True
marker_content: executed-before-validation
Impact
- Confidentiality: High. Code runs with the privileges of the loading Python process and may read environment variables, credentials, model data, training data, or local files.
- Integrity: High. The attacker may modify files, model artifacts, predictions, or application state.
- Availability: High. The attacker may delete files, consume resources, or terminate the process.
CVSS v3.1
Score: 7.8 (High)
Vector: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Alternative deployment-specific vector:
For hosted model-upload or model-registry workflows where a service
automatically loads attacker-supplied artifacts, the vector may be closer
to CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H.
Timeline
- Discovered: 2026-06-10
- Vendor notified: 2026-06-10
- Patch released: [unknown]
- Public disclosure: 2026-06-10
Countermeasure
Do not treat the current single-file joblib envelope as a security
boundary. Load only trusted artifacts, or redesign persistence so
metadata and signatures can be verified before deserializing the model
payload. Potential mitigations include separating metadata from the
pickle payload, verifying cryptographic signatures or trusted registry
provenance before loading, using a safer model serialization format where
applicable, and running artifact loading in a restricted low-privilege
sandbox. |
|---|
| Fonte | ⚠️ https://github.com/yzhao062/pyod/issues/697 |
|---|
| Utente | Dem0000000 (UID 98743) |
|---|
| Sottomissione | 10/06/2026 02:54 (1 mese fa) |
|---|
| Moderazione | 12/07/2026 17:47 (1 month later) |
|---|
| Stato | Accettato |
|---|
| Voce VulDB | 377872 [yzhao062 pyod 3.5.0/3.5.1/3.5.2 persistence.py pyod.utils.persistence.load path escalationi di privilegi] |
|---|
| Punti | 20 |
|---|