# 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) ```bash # 1. Reconstruct the 5 fixtures (seed + per-variant Manifest.json) bash build_variants.sh # -> ./models/.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/.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.