Summary
sklearn2pmml CLI loads the input model file using dill.load() as a fallback when joblib.load() fails. The dill library can deserialize arbitrary Python objects — including lambdas, closures, and os.system calls — making it possible for a malicious model file (.pkl, .dill) to execute arbitrary code on the machine running sklearn2pmml.
Affected Version
sklearn2pmml (latest, sklearn2pmml/cli.py)
Vulnerable Code
sklearn2pmml/cli.py:
import dill
# ...
with open(args.input, "rb") as dill_file:
args.input = dill.load(dill_file) # ← arbitrary code executes here
The -i / --input argument is a file path provided on the command line. When joblib.load() fails (e.g. for non-joblib dill files), dill.load() is called without any integrity check on the file content.
Why dill is dangerous
Unlike pickle, dill is explicitly designed to serialize/deserialize almost anything in Python, including:
- Lambda functions and closures
- Class definitions
os.system, subprocess.Popen and other system calls
- Full module objects
A malicious actor can craft a .pkl file that executes shell commands on deserialization:
import dill, os
class Exploit(object):
def __reduce__(self):
return (os.system, ('calc.exe',)) # or any command
with open('malicious_model.pkl', 'wb') as f:
dill.dump(Exploit(), f)
Running sklearn2pmml -i malicious_model.pkl -o out.pmml immediately executes calc.exe (or any shell command).
Attack Scenarios
-
Poisoned model repository: A shared model store (S3, NFS, artifact registry) is compromised and models are replaced with malicious dill files. Any CI/CD pipeline running sklearn2pmml for PMML conversion executes attacker code.
-
Malicious open-source model: A researcher downloads a pre-trained model from an untrusted source and converts it with sklearn2pmml — the conversion itself triggers RCE.
-
Supply-chain attack: Attacker publishes a popular sklearn model file that, when processed by sklearn2pmml, backdoors the conversion machine.
CVSS Score
9.8 CRITICAL — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
(When triggered via a model downloaded from the internet and processed in a pipeline)
Suggested Fix
Option 1 — Warn the user about dill deserialization risks and require an explicit flag:
if args.allow_untrusted:
args.input = dill.load(dill_file)
else:
raise SystemExit(
"ERROR: Input file requires dill deserialization, which can execute arbitrary code.\n"
"Pass --allow-untrusted only if you fully trust the model source."
)
Option 2 — Use joblib only and refuse dill files, or use pickle with a RestrictedUnpickler that whitelists sklearn/numpy classes.
Option 3 — Document the risk prominently in the README so users are aware.
References
Reporter
Younghun Lee — PYPI supply-chain vulnerability research
Summary
sklearn2pmmlCLI loads the input model file usingdill.load()as a fallback whenjoblib.load()fails. Thedilllibrary can deserialize arbitrary Python objects — including lambdas, closures, andos.systemcalls — making it possible for a malicious model file (.pkl,.dill) to execute arbitrary code on the machine runningsklearn2pmml.Affected Version
sklearn2pmml (latest,
sklearn2pmml/cli.py)Vulnerable Code
sklearn2pmml/cli.py:The
-i/--inputargument is a file path provided on the command line. Whenjoblib.load()fails (e.g. for non-joblib dill files),dill.load()is called without any integrity check on the file content.Why dill is dangerous
Unlike
pickle,dillis explicitly designed to serialize/deserialize almost anything in Python, including:os.system,subprocess.Popenand other system callsA malicious actor can craft a
.pklfile that executes shell commands on deserialization:Running
sklearn2pmml -i malicious_model.pkl -o out.pmmlimmediately executescalc.exe(or any shell command).Attack Scenarios
Poisoned model repository: A shared model store (S3, NFS, artifact registry) is compromised and models are replaced with malicious dill files. Any CI/CD pipeline running
sklearn2pmmlfor PMML conversion executes attacker code.Malicious open-source model: A researcher downloads a pre-trained model from an untrusted source and converts it with
sklearn2pmml— the conversion itself triggers RCE.Supply-chain attack: Attacker publishes a popular sklearn model file that, when processed by
sklearn2pmml, backdoors the conversion machine.CVSS Score
9.8 CRITICAL —
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H(When triggered via a model downloaded from the internet and processed in a pipeline)
Suggested Fix
Option 1 — Warn the user about dill deserialization risks and require an explicit flag:
Option 2 — Use
joblibonly and refuse dill files, or usepicklewith aRestrictedUnpicklerthat whitelists sklearn/numpy classes.Option 3 — Document the risk prominently in the README so users are aware.
References
Reporter
Younghun Lee — PYPI supply-chain vulnerability research