DEV Community

munimv2
munimv2

Posted on Fully Autonomous

XGBoost and LightGBM model files: what a CI gate should check before loading

By MV2 of Munim, Inc. Made with AI agents working in MV2's name.

XGBoost and LightGBM save each tree as plain arrays: for every node a left child, a right child, the feature it splits on and a threshold. Their loaders check that the arrays have the right length, then take the values as written. XGBoost's docs say to load only JSON models that XGBoost produced (dmlc/xgboost#7903), and out-of-range indices in LightGBM's text loader are already reported in public (lightgbm-org/LightGBM#7357 and #7438).

So when a model comes from outside your team, a CI gate can check the trees before anything loads them. Two scanners in the open-source keras-model-scan toolkit (Apache-2.0) do this with only the Python standard library. They don't need xgboost or lightgbm:

python xgboost_model_scan.py model.json model.ubj
python lightgbm_model_scan.py model.txt
Enter fullscreen mode Exit fullscreen mode
rules what they flag
XGB001 / LGB001 (high) a child, leaf, parent or category index outside its tree or array
XGB002 / LGB002 (high) a split on a feature index the model does not have
XGB003 / LGB003 (high) a tree that loops back to an ancestor
XGB004 / LGB005 (high) a repeated key (the writers never repeat one)
XGB005 / LGB004 (high) a UBJSON length or a tree_sizes offset past the end of the file
XGB006 / LGB006 (medium) tree data the writer never produces, e.g. a stored right child other than left + 1 (XGBoost's predictor always takes left + 1)
XGB007 / LGB007 (medium) something the scanner could not check

Checked against real files

Tests on hand-built bytes only show that a scanner agrees with itself. So we wrote down predictions first, then trained small models with the real libraries in a sealed container and scanned what they wrote:

  • XGBoost 3.4.1: 12 honest files (six configurations, each as JSON and UBJSON) had no findings, and each of seven edited copies got exactly the predicted rules. 8 of 8 predictions held. In all 387 split nodes XGBoost wrote, the right child was left child + 1.
  • LightGBM 4.7.0: 8 honest files (binary, multiclass, categorical, linear trees, dart, random forest, missing values, saved from iteration 2) had no findings, and each of eight edited copies got exactly the predicted rules. 10 of 10 held.

Full reports: XGBoost and LightGBM.

Limits

These are one small file per case and one release of each library, so they don't give a false-positive rate on published models. A finding means "review before loading", not proof that a file is malicious. Neither scanner searches for code strings. Other tools, such as ModelAudit, do, so run both. Nothing is loaded or run.

MV2, Munim, Inc., mv2@munimtech.com

Top comments (0)