⚠️ Security PoC — PMML XXE (pmml4s / pypmml)
This is not a real model. It is a proof-of-concept malicious .pmml model file for an
XML External Entity (XXE) vulnerability in pmml4s (the Scala PMML library behind the
Python pypmml package). Loading this file with pypmml.Model.fromFile() parses the XML
with an unhardened javax.xml.stream.XMLInputFactory (no setProperty to disable DTDs /
external entities in org.pmml4s.xml.XMLEventReader), so a .pmml model is an XXE vector:
- Arbitrary local file read (out-of-band exfiltration) — the load-bearing impact.
- SSRF (external-entity fetch to an attacker URL) and DTD/billion-laughs DoS — corollaries.
Confirmed on pypmml 1.5.8 / pmml4s_2.13-1.5.8 / OpenJDK 11.
Files
evil_model.pmml— the malicious model.%file;readsfile:///etc/hostname(swap for any path);%dtd;loadsevil.dtdfromATTACKER_HOSTwhich exfiltrates the file's contents over HTTP.evil.dtd— the out-of-band exfiltration DTD (host onATTACKER_HOST:8000).poc_pmml_xxe.py— self-contained harness (plants a harmless canary, runs a local listener, demonstrates file-read + SSRF + DTD-expansion). Harmless: local-only listener, planted canary (not real secrets), bounded DoS.
Reproduce
pip install pypmml # bundles pmml4s_2.13-1.5.8.jar; needs a JRE
python poc_pmml_xxe.py # self-contained: prints file-read / SSRF / DTD results
Note: external entities must be referenced in element text (e.g. <Annotation>), not in an
attribute value (XML well-formedness forbids that and pmml4s rejects it as "Not a valid PMML").
Fix
In org.pmml4s.xml.XMLEventReader, harden the factory:
factory.setProperty(XMLInputFactory.SUPPORT_DTD, false) (and/or disable external entities).
Harmless PoC. This repo is deleted after triage.