A reboot ends an unattended iPhone session: after a cold boot iOS withholds developer services until a person enters the passcode
Lockdown answered. devicectl said unavailable. WebDriverAgent could not start, so the passcode stored on the Mac could not be typed by the one process that types it. Our runner's repair routine now stops one rung short of a reboot, on purpose.
On 9 September 2026 a reboot cleared a wedged test session on our benchmark iPhone and ended
the unattended run in the same move. After the cold boot the phone answered on USB, reported
"PasswordProtected": true, and withheld the developer services that
devicectl and WebDriverAgent need, so the passcode stored on the Mac could not be typed by
the one process that types it. From that day our rule has been written into the runner: a reboot
ends the session, and the automated repair path is not allowed to use one.
A wedge that only a reboot cleared, and a reboot that needed a person
The fault came first. A device-side test session stopped answering with
DTX capability handshake timed out and zero runner processes on the phone. Nothing sent
over the wire cleared it. A reboot did. The cause, as far as we could reconstruct it, was memory
pressure on the Mac killing a half-open test session, which left the phone holding the device side of
a conversation whose other end no longer existed (FINDINGS.md section 24).
The reboot then produced the state that matters more. A freshly booted iPhone with a passcode keeps most user data under a key that is not available until the passcode has been entered once. Apple's Platform Security guide calls that class Protected Until First User Authentication and makes it the default for third-party app data. Forensic tools call the state BFU. On our iPhone 17 Pro Max on iOS 26.6 the practical reading was three lines:
lockdown: answering, "PasswordProtected": true
devicectl: unavailable <- CoreDevice / developer services withheld
WebDriverAgent: cannot start, so it cannot type the passcode it has
That is a loop with no exit on the Mac side. Typing the passcode is what WebDriverAgent does when a run finds the phone locked, and WebDriverAgent is the thing that will not start. We read it as a security property working as designed.
Two dates since then widen the blast radius. On 14 September 2026 Apple released iOS 27 and, for phones staying on 26, iOS 26.7 with more than 80 security fixes, 75 of them shared with iOS 27 (MacRumors, 14 September 2026). Installing either one is a reboot. And since iOS 18.1 a phone that has sat locked for 72 hours restarts itself into the same state, a timer the Secure Enclave keeps and the kernel acts on, as reverse engineered by Jiska Classen and reported by heise on 20 November 2024.
What answers after a cold boot, and what that implies
| layer or event | reading | consequence for an unattended rig | source |
|---|---|---|---|
| lockdown over usbmux | answering, "PasswordProtected": true | the phone looks present to any check that only asks whether it is connected | FINDINGS.md s.24 |
xcrun devicectl | device unavailable | no process launch, no process list, no install | FINDINGS.md s.24 |
| WebDriverAgent runner | cannot start | no /status on port 8100, and no way to type the stored passcode | FINDINGS.md s.24 |
| Data Protection class for third-party app data | Protected Until First User Authentication by default | data stays keyed to a passcode entry that has not happened yet | Apple Platform Security guide |
| Inactivity reboot | restart after 72 hours with no passcode or biometric entry, since iOS 18.1 | a rig phone left locked over a long weekend reboots itself into this state | heise, 20 Nov 2024 (Classen analysis) |
| iOS 27 and iOS 26.7 | both released 14 Sep 2026; 26.7 carries more than 80 security fixes | every install is a reboot, so an automatic overnight update ends the run | MacRumors, 14 Sep 2026 |
| Activation wedge (apps stop coming forward) | first recorded as reboot-only, later fixed by terminating the runner pid | the reboot was the wrong remedy for that fault; seconds, no person | FINDINGS.md s.27 and s.29, 9 Sep 2026 |
Runner.heal() | three steps: type the passcode if locked, restart the forward, recycle the runner | no reboot step, by design | phoneshell/bench/runner.py |
The seventh row is the one that changed our behaviour most. Section 27 of our findings concluded
the same day that app activation degrades under sustained automation and "only a reboot restores
it". Section 29 overturned that within hours: the WebDriverAgent process was alive and deaf,
devicectl process launch against an already-running app returned success without
replacing it, and terminating the runner by pid brought it back on the first attempt. A reboot clears
every state at once, which makes it useless as evidence about which state was wrong, and on a phone
with a passcode it costs the session besides.
The recovery ladder, and where it stops
Every failure we have seen on the rig sits on one of five rungs. The first four are recoverable from the Mac. The fifth is not, and the runner's repair routine stops above it on purpose: its docstring says it "will NOT" reboot, citing section 24.
What it means if you run phone agents overnight
Schedule reboots, never use them as repair. A reboot at the start of a run, with a person there to type the passcode, costs one boot and one passcode entry. A reboot at 03:00 costs every task after it, and those tasks do not fail in an interesting way: they are not scored at all, which in our reporting makes the run shorter and leaves its score untouched. Our runner reports never-attempted tasks as not scored rather than failed, so this shows up as missing rows in the results.
Treat an OS update as a scheduled reboot. With iOS 27 and iOS 26.7 both on offer since 14 September 2026, a rig phone with automatic updates on will take one of them overnight, reboot into BFU, and also come back with a runner built against the previous build. That combines rung 4 and rung 5 of the ladder in a single event. Our judgement: automatic updates should be off on a benchmark phone, and updates should be a planned step with a person present and a rebuild immediately after.
Never leave the rig phone locked. The 72 hour inactivity reboot only counts time since the passcode or Face ID was last used, and our prep step sets Auto-Lock to Never before a run for exactly this family of reasons. That setting once failed to stick silently on this device, and the phone locked mid-run, which is why the prep step now checks for the checkmark in the chosen row rather than for the word Never on the page.
Guard the cause. The wedge that forced this reboot came from the Mac rather than the
phone: a memory-starved Mac killed a half-open test session. A long device job should not share a
machine with anything that can exhaust memory, and two jobs should not share a phone; ours take an
exclusive flock in phoneshell/lock.py after a second process once drove the
phone alongside a sweep for seventy minutes and sixty-four rows had to be discarded.
The option we have not tested: our findings file names a passcode-less test device as "the real answer" for anyone running this seriously, because it could be rebooted freely. We have not run that configuration, so treat it as a hypothesis. It also trades away the data protection that makes the phone a realistic user's phone.
Check it yourself
You need a passcode-protected iPhone with Developer Mode on, a Mac with Xcode, and a willingness to reboot the phone. Read the state before and after.
# before the reboot: the phone is trusted, developer services are up
xcrun devicectl list devices
pymobiledevice3 lockdown info | grep -i -E 'PasswordProtected|ProductVersion|BuildVersion'
curl -s -m 3 localhost:8100/status | head -c 200
# reboot from the phone (or from the Mac), do not touch the screen afterwards, then:
xcrun devicectl list devices # expect the device listed as unavailable
pymobiledevice3 lockdown info | grep -i PasswordProtected # still answers: true
xcrun devicectl device info processes --device <udid> # expect a failure, not a list
# enter the passcode on the phone once, then repeat: everything comes back
# our code: the repair routine and its refusal to reboot
grep -n "def heal" -A 20 phoneshell/bench/runner.py
sed -n '/^## 24\./,/^## 25\./p' FINDINGS.md
sed -n '/^## 29\./,/^## 30\./p' FINDINGS.md
For the 72 hour timer you need a locked phone and three days, or Jiska Classen's write-up via the heise report linked below. For the update dates, Apple's release notes for iOS 26.7 and the MacRumors report of 14 September 2026.
What would prove this wrong
- Reboot a passcode-protected iPhone on iOS 26.7 or iOS 27 and have
devicectllist it as available and launch the WebDriverAgent runner before anyone enters the passcode. That would mean the gating we saw on iOS 26.6 was version-specific. We predict it holds on every iOS 27.x release through 30 June 2027. - Find a supported Apple setting, profile or Xcode option that lets an XCTest runner start in BFU on a phone with a passcode. If one exists, rung 5 becomes a scriptable rung and the rule in this note is overcautious.
- Reproduce the DTX handshake wedge and clear it without a reboot. We found no such path; section 29 found one for a different wedge after section 27 had declared it reboot-only, so we hold this one loosely. One incident, so treat the reboot-only claim as an anecdote until it repeats.
Sources
- phoneshell, FINDINGS.md sections 24, 27 and 29 (9 September 2026), and phoneshell/bench/runner.py Runner.heal. https://github.com/Blomega/phoneshell/blob/main/FINDINGS.md
- Apple, Apple Platform Security: Data Protection classes (Protected Until First User Authentication). https://support.apple.com/guide/security/data-protection-classes-secb010e978a/web
- Ben Schwan, heise online, Reboot after inactivity: How Apple's new iOS security feature works, 20 November 2024 (analysis by Jiska Classen). https://www.heise.de/en/news/Reboot-after-inactivity-How-Apple-s-new-iOS-security-feature-works-10077069.html
- Jiska Classen, Reverse engineering iOS 18 inactivity reboot, naehrdine blog, November 2024. https://naehrdine.blogspot.com/2024/11/reverse-engineering-ios-18-inactivity.html
- MacRumors, iOS 18 security feature causes iPhone to reboot after three days of inactivity, 14 November 2024. https://www.macrumors.com/2024/11/14/ios-18-3-day-iphone-reboot/
- Juli Clover, MacRumors, Apple releases iOS 26.7 with security fixes, 14 September 2026. https://www.macrumors.com/2026/09/14/apple-releases-ios-26-7/
- Appium WebDriverAgent, v16.12.8 released 11 September 2026 (npm registry). https://registry.npmjs.org/appium-webdriveragent