Summary
The pull request adds four artifacts to iLEAPP's logarchive module. Two read statedumps titled “TCC Authorization Cache”, which show what a process had cached about privacy permissions at the moment it wrote the dump. Two read statedumps titled “CLLocationManagerStateTracker”, which show the flags and settings of a location manager. Each has a row-per-dump view and a collapsed summary.
Values are copied as logged and no meaning is assigned. The dumps do not name the application they describe. The only attribution is the process that wrote them, and a row is a lead, not proof of consent or of use.
- 4artifacts added
- 409lines of parser code
- 542 and 278TCC rows on two research images
- 2,174 and 514location state rows on the same two
Methodology note
Drafted with AI assistance and reviewed by the author before publication.
The issue
An examiner is asked which apps may use the address book or location, and whether anything held a live location manager in the background. Two places can help. The permission database TCC.db names the requesting app and gives a last modified time. The unified log holds statedumps: records in which a process writes out a block of its own state. Until this contribution iLEAPP did not read the statedumps of the permission cache or of the location manager.
They are awkward to read for two reasons. First, a statedump record has no subsystem and no category, and the table iLEAPP builds does not keep the record's event type. Every marker that selects by subsystem finds nothing, so a statedump has to be found by the first line of its message (Figure 1). Second, they repeat. Some processes wrote up to 252 TCC dumps and up to 1,764 location dumps on one image, most of them identical to an earlier one. Printed one row per dump, the report holds thousands of rows that describe a few states.
Show this figure as a table
| Field | Value |
|---|---|
| Timestamp | 2026-03-14 10:00:07 |
| Process | /usr/libexec/faketccd |
| Subsystem | (empty) |
| Category | (empty) |
| Message, line 1 | title: TCC Authorization Cache |
| Message, line 2 | Object Type: |
The essence
Each dump kind has two artifacts. One gives a row for each cached entry of each dump, or for each dump. The other collapses identical content and gives the first and last dump that held it and the number of dumps. Both state that they show content, not change: two rows for one process with different content mean that dumps held different content, not that a permission changed.
| Artifact | One row is | Rows, iOS 26.5.2 | Rows, iOS 26.6 |
|---|---|---|---|
logarchive_tcc_cache | One cached entry in one dump | 542 | 278 |
logarchive_tcc_cache_summary | One distinct entry per process, with first and last dump | 103 | 99 |
logarchive_location_state | One dump, with 16 logged keys as columns | 2,174 | 514 |
logarchive_location_state_summary | One distinct content per process and PID | 119 | 156 |
The TCC rows give the service, two object addresses, the auth right, reason and version as logged, and the writing process. The location rows give keys such as the updating-location flag, the background-updates flag and the desired accuracy, with the remaining keys in an Other Fields column.
Our methodology
Format discovery. Statedump messages are a title line, two object-type lines and a body. The TCC body is a JSON object whose descriptions hold object addresses and no bundle identifier or process name. The location body is not valid JSON, because the last value ends in a comma, so it is read line by line. The two title lines are the only handle, and the patterns are anchored at the start of the message so that a title quoted inside another message does not match.
Collection and filter. Both markers are added to the collection step as well as to the artifacts' filters, since a dependent artifact only sees what the collection step kept. A test fails if a marker an artifact reads is missing from the collection step.
Synthetic fixture and tests. A synthetic log show export with invented process paths, PIDs and addresses covers each fallback, with decoys. Its generator marks every invented shape. Twenty-eight tests in four groups run the real two-stage chain, check the markers, test the parsers, and check that the fixture is reproducible. A deeply nested body is treated as unreadable, not as an error, and a key inside another word is not read.
Behavior on missing or odd data. An empty dump is collected but gives no row. A dump whose body cannot be read gives one row with the body as logged and every other field blank. Keys that a later release adds go to Other Fields.
Validation on real images. On two corpus sysdiagnoses, no body failed to read and every authorization record matched the expected shape. The image with iOS 26.5.2 gave 518 collected TCC dumps, 481 with entries and 542 rows. The image with iOS 26.6 gave 331 dumps, 254 with entries and 278 rows (Figure 3). Auth Right read Allowed, Limited, Denied or Unknown, and Reason read Entitled, User Consent, Service Policy or None. The artifact does not say what those words or a Version of 1 or 2 denote.
Show this figure as a table
| Dump | Reader | Fallback |
|---|---|---|
| TCC cache | JSON object, regex on record text | Empty: no row. Unreadable: one row with the text |
| Location state | Line by line, 16 known keys | Other keys and odd lines go to Other Fields |
Show this figure as a table
| Image | TCC dumps collected | TCC rows | TCC summary rows | Location rows | Location summary rows |
|---|---|---|---|---|---|
| iOS 26.5.2 | 518 | 542 | 103 | 2,174 | 119 |
| iOS 26.6 | 331 | 278 | 99 | 514 | 156 |
The value
Who benefits. Examiners who need to say which process held a cached permission verdict or a live location manager, and researchers who want to know what the permission cache looks like across builds.
Which question can now be answered. “Which process wrote a TCC cache dump with an entitled address-book entry, and when?” and “Which processes wrote a location dump with updating-location true?” On the two images most TCC rows were entitled address-book entries (381 of 542 and 230 of 278), mostly written by processes outside app bundles (341 and 195). Updating Location read true on 62 and 42 location rows. Twelve of the 62 were written by processes in app bundles on the first image, and none of the 42 on the second.
What it changes in a case. The dumps add the writing process and a dump time to what TCC.db gives, which is the requesting app and a last modified time (Figure 4). An examiner can use a dump as a lead for a process to look at next. A row with updating-location true shows that state at the dump time. It does not show that a position was obtained, stored or used.
Limits. Only processes that wrote a dump inside the log's window appear, so an empty result is not evidence that no permission was cached. A dump says nothing about when a permission was granted. How a dump entry relates to a TCC.db row is not established.
Show this figure as a table
| Image | Process paths in dumps | Apps with a TCC.db row |
|---|---|---|
| iOS 26.5.2 | 42 | 7 |
| iOS 26.6 | 38 | 7 |
Where this sits in the Lab's research
This contribution supports Lab Technical Report LAB-TR-0012, “What the iOS Unified Log Says About Device Security Controls: Most Leave a Trace, Few Record a Change” (preprint, not peer reviewed; available on this site, Zenodo deposit pending, so there is no DOI yet). The report lists statedumps selected by their title as one of its marker rules (Section 3.4) and gives the results for both dump kinds in Table 6, including the larger counts in its iOS 27.0 log. It explains why the request lines alone do not answer the question: the requester of a permission request is withheld, and the statedumps add the cached verdict and reason per writing process without naming the application. That is the report's central finding in a small case: the control leaves a trace, and the trace shows a last known state, not a change.
The white paper LAB-TR-0017 (preprint on this site; Zenodo deposit pending) maps where settings live on disk and does not cover the unified log, so it does not cover this contribution. The method above is from the pull request and LAB-TR-0012.
Sources
Every number in this post is listed here with where it comes from. Figures use these numbers or invented example values, marked as such.
| Number or claim | Where it comes from |
|---|---|
| 4 artifacts; 409 lines added to logarchive.py; merged 20 October 2026 | Pull request metadata and diff |
| 518 and 331 TCC dumps collected; 481 and 254 with entries; 542 and 278 rows | notes of logarchive_tcc_cache in the diff; pull request body |
| Summary rows: 103 and 99 (TCC), 119 and 156 (location) | sample_data of the two summary artifacts in the diff |
| 2,174 and 514 location dumps and rows; 55 and 44 distinct process paths | notes and sample_data of logarchive_location_state in the diff |
| Up to 252 TCC dumps and up to 1,764 location dumps from one process, iOS 26.5.2 image | notes of the two dump artifacts in the diff |
| 381 of 542 and 230 of 278 rows are entitled address-book entries; 341 and 195 by processes outside app bundles | notes of logarchive_tcc_cache in the diff |
| Updating Location true on 62 and 42 rows; 12 and 0 by processes in app bundles | notes of logarchive_location_state in the diff |
| 42 and 38 process paths in the dumps; TCC.db address-book rows for 7 apps on each | notes of logarchive_tcc_cache in the diff |
| 28 tests in four groups | Count of test functions in test_logarchive_statedumps.py in the diff |
| Statedumps selected by title; Table 6 results; requester withheld in the request lines | LAB-TR-0012, Section 3.4, Table 5 and Table 6 |