PMML TransformationDictionary Output Flip PoC
This repository contains a proof-of-concept demonstrating that PMML model files embedding a TransformationDictionary / DerivedField silently invert an input feature during scoring, and that pypmml's public API does not expose the applied transformation.
Vulnerability Summary
pypmml (≤1.5.8) parses PMML TransformationDictionary / DerivedField elements and applies them automatically during predict(). The Model object's public API does not expose the transformation:
model.inputFieldsreturns onlyMiningSchemafield names — the derived field is not listedmodel.transformationDictionarydoes not exist (raisesAttributeError)model.predict()silently applies the transformation with no warning
A PMML model that inverts petal_length via petal_length_eff = -petal_length + 7.0 produces predictions that are the direct opposite of a model using raw petal_length. A downstream consumer relying on model.inputFields cannot detect that the feature has been transformed.
Affected Product
- Package:
pypmml - PyPI: https://pypi.org/project/pypmml/
- Confirmed affected: 1.5.8 (current release)
- Format: PMML 4.4 (Predictive Model Markup Language)
Files
| File | Description |
|---|---|
craft_pmml.py |
Generates benign_reference.pmml and crafted_transform_flip.pmml |
demonstrate_output_flip.py |
Scores both models — shows complete prediction flip |
inspect_model.py |
Confirms model.transformationDictionary is inaccessible via pypmml API |
benign_reference.pmml |
Reference PMML without TransformationDictionary |
crafted_transform_flip.pmml |
PMML with hidden petal_length inversion |
expected_output.txt |
Expected script output |
requirements.txt |
pypmml>=1.5.8 |
Reproduction
pip install pypmml
python craft_pmml.py
python demonstrate_output_flip.py
python inspect_model.py
Key Output
BENIGN model:
[low_petal] petal_length=1.4 predicted_target=benign prob_malignant=0.1091
[high_petal] petal_length=5.5 predicted_target=malignant prob_malignant=0.9991
ADVERSARIAL model (hidden petal_length inversion):
[low_petal] petal_length=1.4 predicted_target=malignant prob_malignant=0.9982
[high_petal] petal_length=5.5 predicted_target=benign prob_malignant=0.2689
model.inputFields IDENTICAL for both: ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']
model.transformationDictionary: AttributeError (does not exist)
Root Cause
In PMML 4.4, TransformationDictionary / DerivedField defines named computed features available globally to models. When a RegressionTable references petal_length_eff (a derived field) rather than raw petal_length, pypmml substitutes the computed value transparently. The Model object exposes no method or attribute to enumerate or inspect active DerivedField definitions. model.inputFields reflects only the MiningSchema, which lists the original feature names without any indication that derived transformations are applied.
Impact
Applications loading PMML models from external sources cannot verify the feature processing pipeline via pypmml's public API. A model whose MiningSchema correctly lists expected feature names may embed arbitrary input transformations in TransformationDictionary that silently invert or remap feature values, producing predictions opposite to those expected from the stated input contract.