PyOD 3.6.2: security release (CVE-2026-15529)
This release hardens model persistence against unsafe deserialization.
Security fix
pyod.utils.persistence.load() and pyod.utils.persistence.compat_load() now require an explicit trusted=True before they will deserialize a pickle/joblib artifact. Previously both unpickled the file first, so the envelope, schema, and strict=True checks ran only after any embedded code had already executed. The trust guard now runs before joblib.load(), so those dependency checks are never mistaken for a safety boundary. (CVE-2026-15529; addresses #697 and PR #698 by @3em0.)
Breaking change
load() and compat_load() now raise ValueError unless called with trusted=True, including on artifacts you saved yourself with save(). Update existing round trips:
from pyod.utils.persistence import load
clf = load("model.pyod.joblib", trusted=True)The internal fall-through from load() to compat_load() forwards the acknowledgement automatically, so load(path, trusted=True) still recovers legacy dtype-mismatched artifacts in a single call.
Also in this release
- Persistence guide, decision tree, troubleshooting table, and the save/load example updated to pass
trusted=True. - Regression tests for both loaders' guard and the internal trust forwarding.
Reviewed via /implement-review (Codex, two rounds).