YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
Core ML .mlpackage rootModelIdentifier crash PoC
Proof-of-concept for a deterministic NULL-pointer-dereference crash (DoS) in
Apple's Core ML model-package compilation path, triggered by a malformed
.mlpackage whose Manifest.json contains a present but empty or unresolved
rootModelIdentifier.
This PoC is harmless: it contains only a benign public model and malformed manifest metadata. It does not execute code, read files, or escape any sandbox.
The bug (one sentence)
When rootModelIdentifier is absent, Core ML returns a controlled error
(Failed to look up root model); when it is present but resolves to no
itemInfoEntries item (empty string, or a UUID not in the package), Core ML
dereferences a null pointer and the caller process crashes with SIGSEGV /
exit 139. Inconsistent validation, not by design.
Affected callers (all crash on the same package): MLModel.compileModel(at:)
(Swift), CoreML.MLModel.compileModelAtURL_error_ (Python/PyObjC),
xcrun coremlcompiler compile (CLI), and xcodebuild via its built-in
coremlc generate build rule.
Repository layout
seed.mlpackage.zip # one valid Core ML package (shared model + weights), zipped
manifest-baseline.json # the 5 Manifest.json variants (the ONLY thing that differs)
manifest-root_id_missing.json
manifest-root_id_empty.json
manifest-root_key_absent.json
manifest-root_points_to_weights.json
build_variants.sh # unpacks the seed and rebuilds the 5 byte-identical fixtures
CoreMLCompileOne.swift # minimal Swift reproducer
CoreMLPyObjCCompileOne.py # minimal Python/PyObjC reproducer
provenance-source-url.txt # upstream seed model provenance (MIT)
provenance-upstream-Sudoku-Solver-Pro-9x9-README.md
SHA256SUMS
The model file and weights are identical across all five variants, so they are
shipped once as seed.mlpackage.zip. Each variant is that seed with its
Manifest.json swapped — build_variants.sh reconstructs all five
byte-identically to the packages used in the report.
Reproduce (macOS with Xcode / Core ML)
# 1. Reconstruct the 5 fixtures (seed + per-variant Manifest.json)
bash build_variants.sh # -> ./models/<variant>.mlpackage
# 2. Build the minimal reproducer and run every variant
swiftc CoreMLCompileOne.swift -o /tmp/coreml-compile-one
for v in baseline root_id_missing root_id_empty root_key_absent root_points_to_weights; do
/tmp/coreml-compile-one "models/$v.mlpackage"; echo "$v -> exit $?"
done
Expected result (the differential)
| Variant | Manifest.json change | Result | Exit |
|---|---|---|---|
baseline |
none (valid) | compiles + loads | 0 |
root_id_missing |
rootModelIdentifier = UUID not in itemInfoEntries |
SIGSEGV | 139 |
root_id_empty |
rootModelIdentifier = "" |
SIGSEGV | 139 |
root_key_absent |
rootModelIdentifier key removed |
controlled error | 0 |
root_points_to_weights |
rootModelIdentifier = weights item UUID |
controlled error | 0 |
The root_key_absent control proves Core ML already has a safe rejection path
for a missing root model; only the present-but-unresolved states crash.
Alternative (Python, no Swift): python3 CoreMLPyObjCCompileOne.py models/<variant>.mlpackage
(requires pip install pyobjc-framework-CoreML).
Open-source correlation
The same inconsistency is visible in apple/coremltools
(modelpackage/src/ModelPackage.cpp, getRootModel() throws on absent key but
returns an unchecked nullptr for a present-but-unresolved key). In pure
open-source coremltools (Python) this null surfaces as a controlled
AttributeError; the native SIGSEGV is in Apple's compiled Core ML consumer.
Non-claims
This PoC does not demonstrate code execution, memory corruption beyond a NULL dereference, file disclosure, path traversal, symlink local-file access, scanner bypass, or remote/no-user exploitation. The claim is a narrow crash-only availability issue (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H = 5.5 Medium) in workflows that compile third-party Core ML packages.
Provenance
The seed model is the public, MIT-licensed Hugging Face model
certen/Sudoku-Solver-Pro-9x9 (SudoGPT9x9.mlpackage.zip); see provenance-source-url.txt.
Only Manifest.json was mutated to create the PoC variants.