| name | apple-vuln-research-cve-to-binary-regression |
| description | Validate whether a seed CVE actually maps to a specific Apple macOS/iOS
binary BEFORE porting its PoC. Use when: (1) a research idea / report /
AI suggestion names CVE IDs claimed to affect a specific daemon
(rapportd, sharingd, bluetoothd, etc.) but the IDs were produced by
heuristic or memory and may be wrong, (2) you want to regression-test
a CVE against a patched build without wasting hours on a PoC that
was never reachable in that binary, (3) you need to attribute an
empirical finding (e.g. a mysterious size cap) to a specific CVE
mitigation narrative for a writeup. Covers: the link-chain →
advisory → symbol-match pipeline that cuts CVE-regression triage
from hours to minutes.
|
| author | Claude Code |
| version | 1.1.0 |
| date | "2026-04-21T00:00:00.000Z" |
CVE-to-Binary Regression Audit for Apple Daemons
Problem
When hunting for regressions of historical CVEs in an Apple daemon —
typically during a research loop, a bounty writeup, or a diff review —
the common failure mode is:
- You start with seed CVE IDs someone named ("CVE-XXXX-YYYY affects
daemon Z").
- You spend 2–6 hours digging up the PoC, recompiling, porting.
- You run it, and nothing happens. The PoC was never reachable in
that binary in the first place, because the CVE actually lives in
a different framework, a different daemon, or a different product
line entirely.
- Your only output is a null result, and the idea's original CVE IDs
turn out to have been speculative or mis-remembered.
This skill is the 15-minute validator that should run before
Step 2 — confirm the CVE actually reaches the target binary first,
so you spend effort only on CVEs that can realistically regress.
Context / Trigger Conditions
Trigger this skill when:
- A research idea or ticket context seeds specific CVE IDs ("CVE-XXXX
patched integer overflow in daemon Z, verify it's not regressed")
and you need to confirm the CVE actually lives in Z's code surface.
- You have a patched Apple daemon binary on disk and want to say
"here is the list of public CVEs that could possibly regress in it."
- You've found an empirical mitigation (size cap, auth check, new
validator) in a binary and want to attribute it to a specific CVE
advisory for a writeup.
- You're triaging a bug-bounty submission that names a CVE as
"similar" and you need to rule in/out the actual reachability.
- A prior iteration recommends "port the PoC for CVE-X to daemon Y" —
run this skill first.
Do NOT use this skill for:
- Novel bug-hunting where no CVE ID exists yet.
- Pure static analysis without a target binary.
- CVE-to-source-tree mappings (use symbol lookup in source-drop
builds instead).
Solution — 5-Step Validation Pipeline
Step 1: Dump the Target Binary's Link Chain
BIN=/usr/libexec/rapportd
otool -L "$BIN" | tail -n +2 | awk '{print $1}' > /tmp/linkchain.txt
awk '{
n=split($0, parts, "/");
name=parts[n];
sub(/\.dylib$/, "", name);
sub(/.*\/([^\/]+)\.framework\/.*/, "\\1", $0);
print name;
}' /tmp/linkchain.txt | sort -u > /tmp/components.txt
cat /tmp/components.txt
For Apple daemons, the components that typically carry CVEs (in order
of historical frequency) are:
CoreFoundation, Foundation — rarely land in a daemon-specific CVE
Security, SecureTransport — TLS/cert-chain CVEs
CoreBluetooth, Bluetooth — BT stack CVEs
Network, NetworkExtension — low-level network CVEs
- Any
PrivateFrameworks/* — these are the highest-signal candidates
because they're often the direct wrapper of the daemon's parsing
logic (CoreUtils for rapportd, SharedUtils for sharingd, etc.)
- The daemon's own *.framework (e.g.
Rapport.framework for rapportd,
Sharing.framework for sharingd) — daemon-private framework.
Step 2: Enumerate CVEs Per Framework Name via Apple Advisories
Apple's security advisories group CVEs by component name. Use the
advisory index (https://support.apple.com/en-us/100100) and the
per-update advisory pages. Search strategy:
- Direct component name ("CoreUtils", "Rapport", "Sharing") —
hits the "Component" header of advisory entries.
- Credit name if you know a security researcher who worked on
the area ("Oligo", "Uri Katz", "Alexander Heinrich") — this
surfaces research clusters that advisories group by credit.
- Product scoping: AirPlay / AirDrop / Handoff / Continuity /
iPhone Mirroring / HomeKit — these are Apple-product-level names
that advisories may use instead of framework names.
WebFetch + structured prompt against a specific advisory URL is the
fastest route; for bulk scraping use curl then rg for the component
name. Keep the queries narrow — each advisory is one build.
Critical: seed CVE IDs are frequently wrong. Always validate by
reading the advisory's "Component" field, not by trusting the seed ID.
Step 3: Extract the Advisory's Named Symbols / Messages
For any CVE that passes Step 2, pull the advisory's natural-language
description plus the researcher's writeup (usually linked from the
credit). The writeup typically names specific:
- Function symbols (
mcProcessor_requestProcessSetProxiedProperty)
- Wire-protocol messages (
/getProperty, SETUP RTSP method)
- API names (
CFPropertyListCreateWithData, CFDictionaryGetValue)
- TLV / property / magic strings
Record these as a fingerprint set. Every fingerprint is a
potential grep target in Step 4.
Step 4: Fingerprint-Scan the Target Binary
strings -a "$BIN" \
| grep -E 'mcProcessor|setProxied|getProperty|setProperty|CFPropertyListCreateWithData|CFDictionaryGetValue' \
| sort -u > /tmp/fingerprint-hits.txt
Also scan the ObjC method table and dyld dependency chain for the
named function symbols:
otool -ov "$BIN" 2>&1 | grep -iE 'processProxied|getProperty|setProperty' || true
nm -aU "$BIN" 2>&1 | grep -iE 'mcProcessor|CFPropertyListCreateWith' || true
Interpretation:
- Zero hits for every fingerprint from a CVE's writeup → that CVE
almost certainly does NOT live in the target binary. Rule it out,
move on. Record the negative result.
- Partial hits (some strings present, core function absent) → CVE
lives in a transitively-linked framework, not the binary itself.
Relevant for "is the binary's process affected" but not directly
regressable through the binary's IPC/wire surface.
- All or most hits → CVE is plausibly regressable from the binary.
Proceed to Step 5.
Step 5: Live Regression Probe
Only now write / re-use a probe. For LAN-adjacent daemons the probe
is typically:
- Capture baseline (PID, memory use, open fds).
- Reproduce the CVE's trigger condition (oversize input, malformed
TLV, crafted plist, etc.) against the patched binary.
- Expect either: (a) silent drop with telemetry (the fix), (b)
observable validation error, (c) crash / hang (regression — rare).
- Measure PID stability across 10–100 probes. A still-stable PID
across your probe burst is strong evidence the fix holds.
Write the observation to a finding doc with:
- Binary version (
strings -a | grep version, or --version flag).
- macOS/iOS build (
sw_vers / productversion).
- Exact probe sequence and counts.
- "Not-a-regression" claim with PID-stability evidence.
Verification
You know the skill has been applied correctly when:
- The finding doc has a table
CVE | Component | In-link-chain? | In-binary-strings? | Status.
- Every "ruled out" CVE has a concrete reason (missing string, not
linked, wrong product).
- The "regressable" subset is ≤ a handful of CVEs.
- You spent < 1h per component — not per CVE.
If you find yourself spending hours porting a PoC before Steps 1–4
are complete, stop: go back and run the pipeline first.
Example — rapportd v715.2 / macOS 26.4.1
Seed CVEs (from idea context): CVE-2021-30727, CVE-2022-32849,
CVE-2024-23230 — all claimed to affect rapportd.
Step 1: otool -L /usr/libexec/rapportd → components include
CoreUtils, Rapport, IDS, CoreBluetooth, MediaRemote,
CloudKit, NetworkExtension, Security, Foundation.
Step 2: Apple advisory search by CVE ID:
- CVE-2021-30727 → Component = Crash Reporter (not rapportd).
- CVE-2022-32849 → Component = iCloud Photo Library (not rapportd).
- CVE-2024-23230 → Component = SharedFileList (not rapportd).
- All seed CVEs ruled out at Step 2 in < 10 min.
Component-name search on advisories cross-referenced with credit
"Oligo":
- CVE-2025-31203 → Component = CoreUtils (rapportd links CoreUtils).
Integer overflow, LAN DoS, Oligo AirBorne cluster.
- CVE-2025-24252 etc. (16 more AirBorne CVEs) → Component = AirPlay
(rapportd does NOT link AirPlay.framework). Ruled out.
Step 3: Oligo writeup named mcProcessor_requestProcessSetProxiedProperty,
/getProperty, /setProperty, CFPropertyListCreateWithData,
CFDictionaryGetValue as vulnerable symbols.
Step 4: strings /usr/libexec/rapportd | grep -E ... → zero matches
for any fingerprint. Confirms AirBorne's receiver bugs live in
airplayd, not rapportd. Eliminated 16/17 AirBorne CVEs before
writing any probe.
Step 5: Re-ran an existing PairVerify size-cap probe — body cap
enforced exactly at 16384 bytes, rapportd PID stable across 35+
oversize probes. CVE-2025-31203 patched on v715.2.
Total time: ~45 min. Output: single-page regression audit
ruling out 3 speculative CVEs + 16 scope-wrong CVEs + confirming 1
patched. No PoC porting wasted.
Notes
- Apple's advisory index is occasionally months out of date for
recent research clusters (e.g. AirBorne CVEs only appeared in the
April 28, 2025 "Entry added" line of the Sequoia 15.4 advisory).
Always check both the initial publish date and any re-publish
dates.
- Researcher-credit searches are often more productive than CVE-ID
searches. Oligo, Project Zero, TU Darmstadt (Stute, Heinrich),
Trellix, Trend Micro ZDI, Microsoft MSTIC cluster their reports.
- The "Additional recognition" section of an advisory credits
reporters without CVE assignment. That's a hint that a finding
was reported but Apple deemed it sub-severity — useful for
"near-miss" regression hunting, but those issues will not have
public PoCs.
- On macOS 26, most framework dylibs live in the dyld shared cache
and not on disk. If you need to fingerprint-scan the framework
itself (not the daemon), extract it from
dyld_shared_cache_arm64e
first — or grep the daemon, which transitively includes the
framework's functions as imported symbols.
- This is a Mac-first skill. On iOS you usually need IPSW extraction
to obtain the binary; the pipeline is the same once you have it.
References
- Apple Security Releases index: https://support.apple.com/en-us/100100
- Oligo "AirBorne" AirPlay/CoreUtils CVE cluster:
https://www.oligo.security/blog/airborne
- Related skill:
apple-vuln-research-peer-to-peer-daemon-audit —
live-surface mapping of the daemon itself (use before running this
skill if you don't already have a binary picked).
- Related skill:
apple-vuln-research-security-report-submission —
Apple bounty submission format (use after this skill if a regression
is found).