← Back to research
Defense & recoveryRESEARCH · 7 MIN READ

Spotlight checked my access, then searched beyond it

Spotlight narrowed my app’s search correctly, then widened it with unchecked additions. Establishing the disclosure also meant fixing a weak test baseline and proving which app’s records were actually coming back.

A search lens illuminates one glass index compartment while a second beam widens into neighboring compartments.

My Spotlight test app had put its own records into the search index. That mattered when controls I expected to be empty returned data the app was allowed to see. A successful query could be ordinary behavior, so I had to establish the reader’s own permitted scope before deciding whether the results proved a privacy leak.

Correcting that comparison did not eliminate the finding. Spotlight initially limited a search to my app’s permitted scope, then accepted additions that widened it without the corresponding authorization. The corrected tests returned other apps’ indexed information. Apple now lists the issue as CVE-2026-112628.

The approved search was not the final search

Spotlight answers queries from an index: a collection of information prepared so that the system can find things without opening every original item at search time. Apps contribute records that can contain titles, descriptions and other useful fields. The index remembers which app produced a record, and the search service uses the caller's identity to decide which parts that caller may query.

That separation matters. A system search feature may legitimately bring together information from several apps for a person using their device. An ordinary third-party application should not inherit all of that visibility merely because it can ask the search service a question. The requester and the intended scope of its search need to remain linked.

The affected path initially did that correctly. It used information tied to the caller's connection to reduce the requested scope to the caller's own app. A requesting app's claim about which records it wanted was therefore constrained by who was actually making the request. That is the kind of decision I expect a privileged service to make before reading another app's information.

The failure came later. Additional scope supplied by the caller was combined with the checked scope, broadening the set of records eligible for the search. Those additions did not receive the equivalent authorization. The service then continued with the expanded result. It had validated one set of access rights and used a different set to perform the work.

The important property is the order of those operations. If data influencing access can change after validation, the validity of the earlier decision may no longer describe what will happen. An access check protects the decision it actually checked. It does not bless every alteration made afterward, even if all the processing happens inside the same trusted system service.

My analysis also compared a neighboring route that performed a similar expansion with restrictions in place. That gave me a useful control inside the implementation: comparable work could be guarded, and the service already had the machinery to do it. This was more specific than pointing at a successful response and assuming some permission must be missing somewhere.

My first baseline needed fixing

The early empty results had depended on the test app having no records of its own in the index. When the app contributed identifiable records, some controls returned them legitimately. An empty response could therefore mean the caller was properly restricted, or simply that its permitted part of the index contained nothing. I needed to measure that permitted scope rather than assume it.

After correcting the baseline, I could distinguish the reader’s records from another app’s. The ordinary search route did not return the foreign records; the widened search did. That comparison supported the authorization failure without mistaking the app’s own contributions for a leak.

I also required a known positive result to show that the reader still worked. This was a successful cross-app result used to check the instrument, not an authorized route to the foreign data. Without that check, an empty response could be a failed experiment rather than a successful restriction.

Checking that the index was alive

There was a separate question about where the returned records came from. A result resembling personal data could be a fixed suggestion set or an old collection prepared for another purpose. The evidence needed to distinguish that possibility from access to an index that continued to reflect changes.

I used controlled records from a separate test application to examine that distinction. The contributing app could verify that its own records had reached the index. That verification mattered: a missing result from the unauthorized reader would otherwise be ambiguous if the supposedly searchable record had never become searchable in the first place.

The observed cross-app results followed the controlled records into the index and reflected their deletion. Other controls continued working when those records disappeared, so the disappearance could not simply be credited to a broken reader. This supported a stronger conclusion than finding a static blob of plausible information: the unauthorized result was tracking the controlled producer's live indexed data.

That experiment also had a boundary. I established the live-update behavior with a test producer I controlled. I did not plant controlled records into protected apps such as Messages and Mail and measure their updates in the same way. Those apps supplied captured personal fields in the broader evidence, but the dedicated liveness experiment belonged to the test producer. Combining those statements into “every private app was continuously monitored” would add a result I did not obtain.

The runtime work covered an iPhone and an iPad using a non-debuggable app without a privacy grant for the exposed information. The recorded runs were non-interactive and returned data without consent being given. That establishes what happened under those conditions. It does not require a claim about every possible way an app might be launched or every consent prompt the operating system could display.

What the search results actually revealed

The captured index fields included message subjects, display names, senders and recipients; email subjects and senders; Safari page titles and descriptions; contact phone numbers and email addresses; note and journal title or description text; calendar and reminder titles; and called numbers. These are different kinds of information with different privacy consequences. They should not be flattened into a claim that the app read every underlying document.

A contact address associates a person with a way to reach them. A subject line can disclose what a conversation concerns. A calendar title can describe an appointment. A browsing title can reveal a topic even when the page itself remains inaccessible. These are straightforward implications of the fields returned, not an attempt to guess at the contents of any particular private record.

The index is useful precisely because its entries convey enough meaning to help find things. That usefulness is why unauthorized access to it matters. Keeping the original file closed does not conceal a description that has already been copied into a searchable record. Search privacy has to account for the information stored in the index as well as the permissions on the source material.

At the same time, the distinctions between the fields held. I did not obtain message or email bodies, Photos contents, keychain secrets or access to the underlying databases. Direct file access remained blocked. The disclosure depended on an app running locally. Nothing in this finding demonstrates a remote Internet entry point or a memory-corruption exploit.

Keep the authorization true until the work is done

The repair needed to keep the caller’s restriction in force when the search scope changed. I would not judge that by finding a check near the start of the request; I would judge it by which records the service could return at the end.

Apple describes the repair for CVE-2026-112628 as improved data access restrictions, addressing an issue that could let an app obtain sensitive user data. That public description is consistent with the authorization failure in my report. It does not disclose the exact implementation of the shipped change.

Apple’s Spotlight advisory for CVE-2026-112628

Apple lists the fix in these releases, published October 26, 2026. The list is Apple’s platform coverage, separate from my iPhone and iPad runtime testing.

Install the applicable supported update. Apple’s public entry does not report active exploitation; the findings here describe my research, not evidence of an attack on other users.

Apple credits Santiago Albertengo and Chris Bailey - Short Circuit. Thank you to Santiago and to Apple’s security and engineering teams for their work in getting this issue addressed.

Apple’s published Spotlight credits

The seven Apple CVEs credited to Short Circuit this October

Related: Shortcuts returned private text while resolving action choices

Apple’s advisories checked October 26, 2026.

Published by Short Circuit LLC. Questions or corrections? Contact us