You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

sklearn-pmml-model β€” Unhandled TypeError (float(None)) in GeneralRegressionModel coefficient/intercept parsing on load of crafted PMML (DoS)

Target

  • Package: sklearn-pmml-model
  • Version: 1.0.8 (pip, from PyPI β€” Location: .../site-packages)
  • Affected file: sklearn_pmml_model/linear_model/base.py
  • Affected estimators: PMMLGeneralizedLinearRegressor / PMMLGeneralizedLinearClassifier and their public subclasses β€” PMMLRidge, PMMLLasso, PMMLElasticNet, PMMLRidgeClassifier (all GeneralRegressionModel-backed).
  • Environment: Python 3.13, numpy, scikit-learn; verified by real execution.

Summary

The GeneralRegressionModel parser converts <PCell> coefficient values with a raw float() call over an unchecked attribute lookup. When a crafted PMML file contains a <PCell> that omits its beta attribute, Element.get('beta') returns None, and float(None) raises an unhandled TypeError at model-construction time, before any prediction is made. A sibling AttributeError arises from the same missing guards when the <ParamMatrix> (or <PPMatrix>) element is absent. Any application that loads an untrusted PMML file of this model type is subject to a denial-of-service crash.

Root cause

In sklearn_pmml_model/linear_model/base.py, _get_coefficients -> coefficient_for_parameter:

pp = model.find('PPMatrix')
params = model.find('ParamMatrix')

def coefficient_for_parameter(p):
    if not p:
        return 0

    pcells = params.findall(f"PCell[@parameterName='{p}']")   # line 107 β€” params may be None
    if len(pcells) > 1:
        raise Exception('This model does not support multiple outputs.')

    if not pcells:
        return 0

    return float(pcells[0].get('beta'))                      # line 114 β€” get('beta') may be None

And in _get_intercept:

pp = model.find('PPMatrix')
params = model.find('ParamMatrix')

specified = [p.get('parameterName') for p in pp.findall('PPCell')]   # lines 170/173 β€” pp/params may be None
used = [p.get('parameterName') for p in params.findall('PCell')]
...
return sum([float(i.get('beta')) for i in intercepts])              # line 182 β€” get('beta') may be None

There is no None/attribute validation anywhere in this parser:

  • Element.get('beta') returns None when the crafted <PCell> lacks a beta attribute β†’ float(None) raises TypeError.
  • model.find('ParamMatrix') / model.find('PPMatrix') return None when the element is absent β†’ None.findall(...) raises AttributeError.

Both fire during __init__ (self.coef_ = np.array(_get_coefficients(...)) / self.intercept_ = _get_intercept(model)), i.e. at load time.

Reachability / untrusted-input entry point

The crash is reachable both directly (PMMLRidge('file.pmml')) and through the library's generic untrusted-input loader auto_detect_estimator('file.pmml'), which auto-selects PMMLRidge for a GeneralRegressionModel document and crashes identically.

Proof of Concept

Files in this repo:

  • glm-baseline.pmml β€” NEGATIVE CONTROL. Pristine upstream GeneralRegressionModel test file (linear-model-glm.pmml). Loads cleanly.
  • glm-missing-beta-coef.pmml β€” TRIGGER A. Byte-identical to baseline except one <PCell parameterName="p1" df="1" beta="0.0220430321140947"/> becomes <PCell parameterName="p1" df="1"/> (the beta attribute is removed). Crashes at base.py:114.
  • glm-missing-beta-intercept.pmml β€” TRIGGER B. Intercept PCell p0 loses its beta attribute. Crashes at base.py:182.
  • glm-no-parammatrix.pmml β€” TRIGGER C. The entire <ParamMatrix> element is removed. Crashes at base.py:107 (AttributeError).

Reproduce:

# Trigger A (direct)
python -c "from sklearn_pmml_model.linear_model import PMMLRidge; PMMLRidge('glm-missing-beta-coef.pmml')"

# Trigger A (via untrusted-input entry point)
python -c "from sklearn_pmml_model.auto_detect import auto_detect_estimator; auto_detect_estimator('glm-missing-beta-coef.pmml')"

# Trigger B
python -c "from sklearn_pmml_model.linear_model import PMMLRidge; PMMLRidge('glm-missing-beta-intercept.pmml')"

# Trigger C
python -c "from sklearn_pmml_model.linear_model import PMMLRidge; PMMLRidge('glm-no-parammatrix.pmml')"

Captured evidence (verbatim, real execution β€” sklearn-pmml-model 1.0.8, Python 3.13)

NEGATIVE CONTROL (glm-baseline.pmml):

LOADED OK coef_.shape= (11,) intercept_= -0.839478621884241

TRIGGER A (glm-missing-beta-coef.pmml) β€” identical crash via PMMLRidge and via auto_detect_estimator:

  File ".../sklearn_pmml_model/linear_model/base.py", line 134, in coefficients_for_field
    return [coefficient_for_parameter(pp_cells[0].get('parameterName'))]
  File ".../sklearn_pmml_model/linear_model/base.py", line 114, in coefficient_for_parameter
    return float(pcells[0].get('beta'))
TypeError: float() argument must be a string or a real number, not 'NoneType'

TRIGGER B (glm-missing-beta-intercept.pmml):

    self.intercept_ = _get_intercept(model)
  File ".../sklearn_pmml_model/linear_model/base.py", line 182, in _get_intercept
    return sum([float(i.get('beta')) for i in intercepts])
TypeError: float() argument must be a string or a real number, not 'NoneType'

TRIGGER C (glm-no-parammatrix.pmml):

  File ".../sklearn_pmml_model/linear_model/base.py", line 107, in coefficient_for_parameter
    pcells = params.findall(f"PCell[@parameterName='{p}']")
AttributeError: 'NoneType' object has no attribute 'findall'

The negative control confirms the exact same file loads fine when beta is present, isolating the single-attribute cause.

Impact

Denial of service: an application that loads an attacker-supplied PMML model of the GeneralRegressionModel family (e.g. via PMMLRidge/PMMLLasso/PMMLElasticNet/ PMMLRidgeClassifier or the generic auto_detect_estimator) crashes with an unhandled exception during model construction. PMML files are commonly treated as model-exchange artifacts and passed between parties, so the untrusted-input surface is realistic.

Suggested fix

Validate presence before conversion: raise a clear, documented parse error (or default sensibly) when ParamMatrix/PPMatrix is missing and when a PCell's beta attribute is absent β€” e.g. guard params/pp against None and use float(pcells[0].get('beta', 0)) / explicit None checks with a descriptive ValueError.

Dedup note

This is a distinct code path and crash class from prior sklearn-pmml-model findings:

  • The affected parser is linear_model/base.py (GeneralRegressionModel), not touched by the previously reported tree/forest/SVM/naive-bayes/logistic-regression/neural-network/SparseArray findings.
  • The crash class here is a TypeError from float(None) on a missing beta attribute (plus a sibling AttributeError from a missing ParamMatrix/PPMatrix), which is distinct from the covered AttributeError/IndexError/allocation findings in other model families.
  • No known CVE covers the GeneralRegressionModel beta/ParamMatrix parsing path in sklearn-pmml-model 1.0.8.
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support