Downloads · 30 days
0
MBM7/catboost-duplicate-feature-id-poc
catboost-duplicate-feature-id-poc is a machine learning model from MBM7. Use it for the machine learning task on the model card, and read the license before you ship it in a product.
Status: Preparing for Huntr submission Package: catboost (PyPI) — Yandex's gradient boosting library File / function: catboost/core.py, multiple methods using self.featurenames.index(feature) (lines ~3910, 3981, 4168)…
Downloads · 30 days
0
Access
Public
Updated Jul 22, 2026
Repo size
—
Likes
0
Public
Click a slice to open those files.
.py3.9 KB · 43%
From the Hugging Face model README
Status: Preparing for Huntr submission
Package: catboost (PyPI) — Yandex's gradient boosting library
File / function: catboost/core.py, multiple methods using self.feature_names_.index(feature) (lines ~3910, 3981, 4168)
Class: CWE-706 (Use of Incorrectly-Resolved Name) + CWE-20
Severity: Medium-High — silent model-integrity issue, not a crash.
Several public CatBoost methods resolve a feature given by name via:
feature_idx = self.feature_names_.index(feature)
self.feature_names_ is populated directly from a loaded model file (tested here via CatBoost's JSON model format — a real, documented, supported export/import format). There is no check anywhere in the loading path that feature_id values are unique across the model's declared float features.
Python's list.index() always returns the first matching element. A model file can declare two float features with the same feature_id but different real data (different learned split-point borders) — any name-based lookup silently resolves to the first one, and the second feature's real, distinct data becomes permanently unreachable via any name-based API, with zero error or warning.
poc_catboost_duplicate_feature_id.py:
age, income) and exports it to JSON.feature_id from "income" to "age", keeping its real, distinct border data unchanged.CatBoostClassifier().load_model(path, format="json").pip install catboost numpy
python poc_catboost_duplicate_feature_id.py
=== Loading via the real public API: CatBoostClassifier().load_model(path, format='json') ===
loaded OK, no error. feature_names_ = ['age', 'age']
feature_names_.index('age') resolves to position 0
Position 1's real, distinct border data ([0.76..., 0.89...]) is now unreachable via name-based lookup -- 'age' always resolves to position 0.
CONFIRMED: the second feature's real data is silently shadowed.
A crafted or corrupted CatBoost model file can declare two structurally distinct, independently-trained features under the same name. Any downstream code that asks for statistics, borders, or feature-dependence plots by name silently receives the first feature's data instead — no error, no warning, no structural signal that something is wrong. This can be used to hide or misrepresent a model's actual behavior on a specific real-world input feature.
Validate that feature_id values are unique across features_info.float_features (and equivalent categorical/text feature sections) during model loading, and raise a clear error on a duplicate.
Same broad pattern family — duplicate identifier leading to silent "first wins" resolution so real data becomes unreachable — as separately-reported findings this session in gguf-py (tensor offset aliasing), ollama/ollama's Go GGUF parser (duplicate tensor names), and sklearn-pmml-model (duplicate VectorInstance id) — all first-wins, all missing the same class of uniqueness validation. This is the first confirmed instance of the pattern in a gradient-boosting model format.
Please do not use this PoC against production systems you do not own or have explicit permission to test.