Downloads · 30 days
0
MBM7/coremltools-fill-unbounded-allocation-poc
coremltools-fill-unbounded-allocation-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: coremltools (PyPI) — Apple's Core ML Tools File / function: coremltools/converters/mil/mil/ops/defs/iOS15/tensoroperation.py, fill.valueinference() Class: CWE-789 (Conve…
Downloads · 30 days
0
Access
Public
Updated Jul 20, 2026
Repo size
—
Likes
0
Public
Click a slice to open those files.
.py15.9 KB · 58%
From the Hugging Face model README
fill Operation Unbounded AllocationStatus: Preparing for Huntr submission
Package: coremltools (PyPI) — Apple's Core ML Tools
File / function: coremltools/converters/mil/mil/ops/defs/iOS15/tensor_operation.py, fill.value_inference()
Class: CWE-789 (Convergent Untrusted-Length Allocation)
Severity: High — an 833-byte model file causes ~2.5GB of memory allocation and 10+ seconds of CPU time, purely in Python, on any platform (no macOS or native Core ML runtime required).
CoreML's MIL (Model Intermediate Language) fill operation — the direct equivalent of ONNX's ConstantOfShape — computes its constant-folded value with no bound check on the declared shape:
# tensor_operation.py, class fill
@precondition(allow=VALUE)
def value_inference(self):
return np.full(shape=self.shape.val, fill_value=self.value.val)
self.shape.val comes from a const operation elsewhere in the same MIL graph — fully attacker-controlled in a crafted model file. There is no check on the requested element count before calling np.full().
By default, coremltools's conversion/save pipeline constant-folds fill operations into a plain const before writing the file, which would hide the vulnerable operation from a normally-produced .mlpackage. This PoC works around that by saving with an empty optimization pipeline (pass_pipeline=ct.PassPipeline.EMPTY), producing a legitimate, valid .mlpackage that genuinely contains an un-folded fill op reading its shape from a small const. The declared shape value is then patched directly in the saved protobuf spec (model.mlmodel), changing only the shape constant's 4-byte int32 value — nothing else in the file changes.
The patched file is loaded via coremltools.converters.mil.frontend.milproto.load.load_mil_proto() — the documented, pure-Python, platform-independent function used to reconstruct an in-memory MIL Program from a saved model spec. This is used by any tooling that loads, inspects, or re-converts a saved CoreML model programmatically, independent of the native macOS runtime.
poc_coreml_fill_bomb.py:
pip install coremltools numpy
python poc_coreml_fill_bomb.py
=== Building legitimate .mlpackage (fill op left un-folded) ===
wrote poc_legit.mlpackage
=== Patching shape constant to 500,000,000 ===
patched model.mlmodel is 833 bytes
=== Loading patched file via load_mil_proto() (pure Python, no macOS needed) ===
-> AssertionError after 1.32s, peak RSS=2564.5 MB (allocation already happened before this error): Mismatch between var types in specification vs PyMIL
The AssertionError is an unrelated, incidental type-consistency check that happens to fire after the expensive allocation — by the time it's raised, the ~2.5GB allocation has already occurred. A more carefully crafted file (patching auxiliary type metadata to stay consistent) would very plausibly avoid tripping this check at all, since it isn't in any way related to bounding the shape value.
coremltools.models.MLModel(path) — the top-level "just load a model" convenience API — does not proceed to full compilation on Linux, because it gates on _MLModelProxy, a compiled component only available with the native macOS Core ML runtime (libcoremlpython). This PoC deliberately demonstrates the vulnerability through load_mil_proto() instead, since that function is public, documented, pure Python, and platform-independent — it does not require macOS to reproduce, and represents a real, commonly-used code path (loading/inspecting/re-converting a model's MIL graph) independent of whether the native execution runtime is present.
Any service or tool that programmatically loads or re-converts CoreML model files using load_mil_proto() (or code paths that reach it) — for example, a model conversion/validation service accepting user-uploaded models — can be forced into multi-gigabyte memory consumption and multi-second CPU stalls by a file under 1KB.
Before calling np.full() in fill.value_inference(), validate the requested element count (product of the declared shape) against a configurable sane maximum, and raise a clear error immediately instead of proceeding to allocate.
Same vulnerability class (CWE-789, CULA) and mechanism as a separately-reported finding in ONNX's ReferenceEvaluator ConstantOfShape operator (np.full(tuple(data), value) with an unchecked shape) — different library, different intermediate representation, but the same underlying missing-validation pattern recurring across model-format tooling.
Please do not use this PoC against production systems you do not own or have explicit permission to test.