GluonTS serde deserialization RCE β proof of concept
This repository is a security proof of concept. It demonstrates arbitrary
code execution in GluonTS (gluonts,
tested on v0.16.3) when a serialized predictor is loaded through the public
Predictor.deserialize(...) API.
GluonTS documents its serde format as a human-readable, cross-version
alternative to pickle. However, gluonts.core.serde.decode resolves an
arbitrary dotted class name from the JSON (locate(...)) and calls it with
attacker-controlled arguments (cls(*args, **kwargs)), guarded only by an
incomplete blocklist (eval, exec, compile, open, input). Any other callable β
for example os.system β bypasses the check, so loading a crafted
predictor.json runs commands.
Files
gluonts-config.jsonβ routesPredictor.deserializeto aRepresentablePredictor, whosedeserializereadspredictor.jsonviaserde.load_json.predictor.jsonβ the malicious payload: anos.systeminvocation.
Reproduce
pip install "gluonts==0.16.3"
git clone https://huggingface.co/<this-repo> gluonts-serde-poc
cd gluonts-serde-poc
# gluonts-config.json + predictor.json sit at the repository root
python -c "from pathlib import Path; from gluonts.model.predictor import Predictor; Predictor.deserialize(Path('.'))"
ls gluonts_serde_pwned.txt # marker created => code executed
Predictor.deserialize(Path('.')) loads the serialized predictor from this directory:
it reads gluonts-config.json, routes to MeanPredictor.deserialize, which
calls serde.load_json on predictor.json and thereby executes
os.system("echo pwned_by_gluonts_serde > gluonts_serde_pwned.txt").
Safety
The PoC is benign: the payload only writes a marker file
(gluonts_serde_pwned.txt) into the current directory. It is not real malware.
Replace the string to see that any command runs with the privileges of the
loading process.