YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
sklearn-pmml-model SVM: SupportVector/Coefficient count mismatch β IndexError crash importing a PMML SupportVectorMachineModel
Summary
sklearn-pmml-model crashes with an unhandled IndexError inside the model
constructor when importing a PMML file whose <SupportVectorMachineModel>
contains fewer <Coefficient> elements than <SupportVector> elements.
Importing arbitrary PMML is the library's core purpose, and the two element
lists are independent, attacker-controlled inputs with no bound or consistency
check between them.
- Target package:
sklearn-pmml-model(PyPI) - Version tested:
1.0.8(confirmed latest on PyPI) - Vulnerable file:
sklearn_pmml_model/svm/_base.py, functionget_coefficients()(lines ~201-204) - Crash type:
IndexError(unhandled exception) duringPMMLSVC(...)construction - Reachable entry points: direct
PMMLSVC(path)constructor and the high-levelauto_detect_estimator(path)dispatcher - Environment: clean venv, Python 3.13.12, numpy from
sklearn-pmml-model==1.0.8deps
Root cause
In get_coefficients() the code parses two independent child-element lists
of a single <SupportVectorMachine> β the <SupportVector> ids and the
<Coefficient> values β then uses positions computed against the first list to
index into the second array:
# sklearn_pmml_model/svm/_base.py (lines ~196-204)
for j, svm in enumerate(alt_svms):
start = offsets[i]
end = offsets[i + 1]
ids = support_ids[start:end]
support_vectors = [int(x.get('vectorId')) for x in svm.find('SupportVectors').findall('SupportVector')]
coefficients = [float(x.get('value')) for x in svm.find('Coefficients').findall('Coefficient')]
indices = [support_vectors.index(x) for x in ids]
dual_coef[j, start:end] = np.array(coefficients)[indices] # <-- line 204: IndexError
indices are positions into the SupportVector list (support_vectors), but
they are applied to a different array, np.array(coefficients). Nothing
couples or validates len(<SupportVector>) against len(<Coefficient>). When a
PMML supplies fewer <Coefficient> elements than <SupportVector> elements, an
index that is valid for the SupportVector list exceeds the bounds of the
coefficients array, and numpy raises IndexError inside the constructor. The
counts are pure element-count values taken straight from untrusted XML.
PoC
Starting material is the project's own valid example model
models/svc-cat-pima.pmml (fetched from the upstream repo). It loads cleanly:
36 <SupportVector> / 36 <Coefficient>, dual_coef shape (1, 36).
svc-mismatch.pmml is that file with all but the first <Coefficient>
deleted inside the single <Coefficients> block (now 36 <SupportVector> /
1 <Coefficient>); everything else is byte-identical. Loading it raises
IndexError at svm/_base.py line 204.
Negative control: the unmodified 36/36 file loads OK through both the direct
constructor and auto_detect_estimator (as PMMLSVC, dual_coef (1, 36)),
proving the crash is caused solely by the SupportVector-vs-Coefficient count
mismatch, not by any other structural change.
Reproduce
python -m venv venv && . venv/bin/activate
pip install sklearn-pmml-model==1.0.8
python repro.py
repro.py:
import traceback
from sklearn_pmml_model.svm import PMMLSVC
def run(path, label):
print(f"=== {label}: {path} ===")
try:
m = PMMLSVC(path)
print(" OK -> dual_coef", m.dual_coef_.shape)
except Exception as e:
tb = traceback.extract_tb(e.__traceback__)[-1]
print(" CRASH", type(e).__name__ + ":", e)
print(" SITE", tb.filename.split('site-packages/')[-1], "line", tb.lineno)
run("svc-cat-pima.pmml", "NEGATIVE CONTROL (36 SupportVectors / 36 Coefficients)")
run("svc-mismatch.pmml", "POSITIVE (36 SupportVectors / 1 Coefficient)")
Captured evidence (verbatim, real execution)
=== NEGATIVE CONTROL (36 SupportVectors / 36 Coefficients): svc-cat-pima.pmml ===
OK -> dual_coef (1, 36)
=== POSITIVE (36 SupportVectors / 1 Coefficient): svc-mismatch.pmml ===
CRASH IndexError: index 1 is out of bounds for axis 0 with size 1
SITE sklearn_pmml_model/svm/_base.py line 204
Full traceback (direct constructor):
Traceback (most recent call last):
File "<string>", line 3, in <module>
PMMLSVC('svc-mismatch.pmml')
~~~~~~~^^^^^^^^^^^^^^^^^^^^^
File ".../sklearn_pmml_model/svm/_classes.py", line 249, in __init__
PMMLBaseSVM.__init__(self)
~~~~~~~~~~~~~~~~~~~~^^^^^^
File ".../sklearn_pmml_model/svm/_base.py", line 61, in __init__
get_coefficients(classes, self._n_support, self.support_, svms)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../sklearn_pmml_model/svm/_base.py", line 204, in get_coefficients
dual_coef[j, start:end] = np.array(coefficients)[indices]
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
IndexError: index 1 is out of bounds for axis 0 with size 1
Also reproduced via the public entry point:
auto_detect_estimator('svc-mismatch.pmml') -> IndexError, SITE svm/_base.py line 204
auto_detect_estimator('svc-cat-pima.pmml') -> OK, PMMLSVC, dual_coef (1, 36)
Impact
Any application that imports a user-/third-party-supplied PMML SVM model via
this library (its intended use case) can be crashed with an unhandled
IndexError by supplying a mismatched <SupportVector>/<Coefficient> count.
This is a denial-of-service / robustness defect on untrusted model-file input.
A benign example file can be turned into a crashing payload by deleting a single
XML element.
Suggested fix
Validate len(coefficients) == len(support_vectors) (and that both match the
declared support count) before indexing, and raise a clear parse error
(e.g. a PMML validation exception) instead of letting numpy raise IndexError.
Dedup note
This is distinct from prior sklearn-pmml-model findings:
- SparseArray index/value pairing crash (TreeModel/other) β different file/parser.
- TreeModel recursion / NeuralNetwork allocation DoS β different model type and code path.
- PMML XXE β an XML-layer issue, not an SVM value-consistency issue.
This bug is specific to svm/_base.py::get_coefficients() and the
SupportVector-vs-Coefficient element-count mismatch. No public CVE was found for
this specific SVM coefficient-indexing crash at time of writing.