cmpndry's picture
Add Core ML rootModelIdentifier crash PoC (seed + manifests + rebuild script)
87234eb verified
|
Raw
History Blame Contribute Delete
4.4 kB
# 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/<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.