github doronz88/pymobiledevice3 v11.13.0

latest release: v11.13.1
7 hours ago

Highlights

🐛 --native works again on macOS 27

Starting with macOS 27 the kernel answers the net.inet.tcp.pcblist* sysctls with only the caller's own sockets unless the caller is root, so the native tunnel could no longer find remoted's connection to the device and every --native command (the macOS default for developer services) failed with could not find remoted's RSD connection to the tunnel address. The RSD port is now taken from one nettop sample instead. nettop still sees every process's sockets because it is Apple-signed with com.apple.private.network.statistics; the NetworkStatistics feed behind it gives an unentitled process the same own-uid view, so the entitled binary has to be the client. Still no root, no Xcode, about 0.1 s.

pymobiledevice3 developer dvt ls / --native

restore preflight and restore preflight-requests

Two commands expose what the device reports before a restore, as JSON. restore preflight prints what lockdown reports in normal mode: PreflightInfo (each peripheral updater's identity fields and current nonce), FirmwarePreflightInfo and ApParameters. restore preflight-requests asks restoreserviced on the device to build each updater's TSS request for a given IPSW, the way restored does during a restore, and prints the requests with their ticket and manifest tags.

pymobiledevice3 restore preflight
pymobiledevice3 restore preflight-requests -i iPhone.ipsw --updater T200 --updater Rose

Requests carrying firmware files run to tens of MB, so RemoteXPC now splits requests larger than the peer's frame size into flow-controlled DATA frames instead of hitting a GOAWAY too large frame size.

--tss-batch rides in the AP request and serves on an exact match

The prefetch used to sign the peripherals in a POST of its own and serve a cached ticket whenever the nonce matched. Measured on iPhone18,4 / iOS 27.0, TSS signs the AP ticket and every peripheral ticket in one request, so the prefetched requests now travel inside Recovery's AP request and cost no request at all (if TSS ever rejects the combined request it is retried alone). A prefetched ticket is served only when the device's own DeviceGeneratedRequest matches what was signed entry for entry; any difference falls through to a live request. The prefetched requests also carry the entries restored sends (BMU,BoardID, Rap,FdrRootCaDigest, UniqueBuildID, the baseband manifest key hashes), so they match the device's byte for byte apart from the nonce. Live restore on that device: TSS requests per restore 13 → 10.

🐛 Restore host brought in line with Apple's (iOS 27 / macOS 27)

A sweep of Apple's MobileDevice restore host against ours:

  • SourceBootObjectV5 and DeviceRestoreInfoPreflight are handled, and the advertised data/message types match what Apple's host sends.
  • GlobalManifestPrefix/GlobalManifestSuffix and optional global manifests are honored (macOS 27 restored names the manifest it wants instead of the hardcoded apticket.<class>.im4m).
  • FirmwareData is streamed in FirmwareResponseData chunks with DataDone, as Apple does, instead of one inline blob.
  • Baseband ticket handling no longer depends on whether restored supplied a nonce (Mav25 / iPhone 17 baseband, ported from idevicerestore).
  • The reverse proxy control connection retries for up to 10 s while the device re-enumerates on USB.
  • CrashLog is saved under the pymobiledevice3 home folder, FDRSubmit is no longer advertised, BootabilityBundleV2 is served by the V1 handler, and unknown requests are logged at warning level instead of debug.
  • FirmwareUpdaterPreflight no longer logs a warning: the empty reply is exactly what Apple's host sends for iPhones.
  • The Device repr reports the real ECID, hardware model and Image4 support instead of the literal async.

📚 Restoring and updating guide

docs/guides/restore.md walks through what restore update does step by step, how the firmware is chosen, update versus --erase, the recovery/DFU entry points, then the TSS requests a restore makes and what --tss-batch changes, with the request counts measured on an iPhone18,4 / iOS 27.0.

🔧 Other changes

  • The recovery device table is synced with libirecovery: 49 missing models added (M2–M5 Macs, MacBook Neo, Apple TV 4K 3rd gen, HomePod 2nd gen, iPad 10th gen, …) and two Apple Watch rows corrected; 327 rows, matching libirecovery master.
  • tunneld keeps a close code that arrives in the same read as the /connect handshake accept, so a refused connect relays its real 4404/4502 code instead of a plain 1000.
  • Removed: LockdownClient.reset_pairing(). lockdownd only honors ResetPairing from a local, entitled XPC peer and refuses every host transport with RemoveProhibited (verified on iOS 27.0), so the method could never succeed. unpair() remains the host-side way to remove a pairing.

What's Changed

Full Changelog: v11.12.5...v11.13.0

Don't miss a new pymobiledevice3 release

NewReleases is sending notifications on new releases.