Adds `--fs` flag to bypass the database and scan entitlements
directly from IPSW filesystem DMGs or input folders. Introduces
`--has`/`--without` for required/excluded entitlement key filtering,
`--pem-db` for AEA-encrypted IPSWs, and `--format` (text, tsv, jsonl)
for structured output.
`ipsw download ipsw --kernel` now fetches firmware keys from
theapplewiki and decrypts encrypted kernelcaches inline. Unencrypted
members in the same IPSW pass through unchanged.
- pkg/img4: DecryptPayload reuses Payload.GetData for decompression,
removing the duplicate LZSS/LZFSE branches.
- pkg/kernelcache: ParseImg4Data switches to img4.ParsePayload and
exports ErrEncryptedKernelCache so callers can detect the missing-key
case via errors.Is.
- internal/commands/extract: new keyed remote path with all-or-nothing
preflight; the encryption-status peek lets unencrypted variants
succeed even when the wiki has no entry for them.
closes#1193
Introduces direct OTA file diffing without requiring pre-extraction.
Users can now pass `.ota`/`.aea` files directly to `ipsw diff` alongside
existing IPSW and directory input modes.
Key additions:
- `internal/diff/ota_inputs.go`: OTA-specific input handling including
cryptex mounting, kernelcache extraction, firmware parsing, iBoot
parsing, and feature flag collection from mounted volumes
- `inputModeOTA` enum variant in `directory_inputs.go`
- `--key-db`, `--key-val`, and `--insecure` flags on `diff` command for
AEA-encrypted OTA decryption
- AEA key database lookup mirroring the `ota` command's key resolution
- Magic-byte-aware error handling: AEA/AA files propagate decryption
errors while ambiguous ZIPs fail silently (not-an-OTA)
- Validation rejects partial/delta and RSR OTAs with actionable messages
- Comprehensive unit tests covering all new helpers
- Add `otaFilenameCandidates` to strip all known extensions (.aea,
.ota, .zip) and generate a fallback candidate from the last
underscore-delimited segment (e.g. downloaded filenames like
`iPhone18,1_23F5043k_<hash>.aea` now match DB entries keyed by
`<hash>`)
- Add test covering the downloaded-filename → archive-stem lookup
- Serialize `GetPayloadFiles` and `PayloadFiles` loops (remove
`errgroup` concurrency) to fix data races and ensure correct
error propagation with explicit resource cleanup
- Add `ErrCryptexNotFound` sentinel error for programmatic detection
- Add `system-arm64e` and `system-x86_64h` as explicit cryptex
selector variants
Strip build-specific keys (versions, SDK info, copyright, etc.)
from Info.plist and version.plist before diffing KDKs, so diffs
reflect meaningful structural changes rather than build metadata.
Replace the `github.com/strukturag/libheif-go` CGo dependency with
macOS-native `sips` for HEIC/AVIF wallpaper thumbnail conversion.
- Drop `libheif` from go.mod, Makefile, Goreleaser config, and CI
- Remove `cgo` build tag requirement from wallpaper package
- Implement `convertWithSips()` using temp files and the `sips` CLI
- Refactor thumbnail decoding into `extractThumbnailPreview()` helper
- Update tests to cover sips-based HEIC conversion path
- Remove POST /diff/files endpoint that allowed arbitrary host file reads
(CWE-22); clients must now read files locally and POST content to
/diff/blobs instead
- Add validatePublicURL() to /info remote endpoints, rejecting URLs that
resolve to loopback, private, link-local, or multicast addresses to
prevent SSRF; also remove attacker-controlled proxy/insecure params
- Add SanitizeArchivePath() helper that verifies extracted archive entry
paths stay within the destination directory (zip-slip / tar-slip,
CWE-22); replace bare filepath.Join(dest, filepath.Clean(name)) calls
in SearchZip, OTA parser, AA payload extractor, and ota_extract
- Fix server listen address to use net.JoinHostPort to respect Host config
- Add `--build`, `--train`, `--app`, `--version` flags to filter
releases before interactive selection
- Show a TTY progress bar while fetching the PCC transparency log
- Resolve OS IPSW versions via partial-zip of BuildManifest.plist,
caching results in `pcc_versions.json` to avoid redundant fetches
- Display build/train/app metadata in release list and info output
- Preflight HEAD-check all assets before downloading to catch CDN
propagation delays early
- Sort releases by timestamp (newest first) instead of log index
- Auto-generate output directory name from release index and build
- Promote `go-isatty` from indirect to direct dependency
Notifications persist on disk in a SQLite store after dismissal —
including "disappearing" message previews from Signal/iMessage/etc.
Inspired by objective-see/AuRevoir.
ipsw notif --apps # bundle IDs with record counts
ipsw notif -a com.apple.mail # one app's notifications
ipsw notif --json # all records as JSON
ipsw notif --raw # full bplist dump per record
Decoder pulls req.{titl,subt,body} via map walk (go-plist silently
no-ops nested struct fields). DB located at the macOS 26 group
container with fallback to the legacy DARWIN_USER_DIR path; surfaces
a clean FDA hint when TCC denies the read. Reuses glebarez/go-sqlite
already in tree, cgo-free, darwin-only.
- Support controlSize=0 (full-replacement) BXDIFF50 patches by
decompressing XZ/PBZX streams directly instead of raw extraction
- Add decompressStream helper that handles both raw XZ and PBZX formats
- Extract patch from ZIP before base-file lookup so temp file is always
cleaned up on skip
- Stream patch file instead of loading entirely into memory
When `--install` succeeds, automatically remove on-disk private key
files (.key and .p12) since the Keychain becomes the canonical store.
The `--keep-key` flag opts out of this cleanup, and clear warnings are
emitted whenever key material remains on disk.
- Add `--platform` flag (ios, macos, tvos, catalyst) to select the
correct certificate and profile types per platform
- Map each platform/type combination to the appropriate ProfileType
- Extract `profileTypeNeedsDevices` helper to cover all dev/adhoc
profile types across platforms
- Auto-register the host Mac as a development device when no devices
are found and platform is macos/catalyst
- Fix `DeviceCreateRequest` to omit `deviceClass` and `model` fields
rather than hard-coding iPhone values
- Initialize profile relationship slices before appending so
json.Marshal emits `[]` instead of `null`
- Bundle cert + generated key into a password-protected .p12 file
using go-pkcs12 (legacy 3DES for macOS Keychain compatibility)
- Import the .p12 via `security import` so cert and key are properly
paired as an identity in the login keychain
- Auto-download and install the Apple WWDR G3 intermediate cert to
ensure a valid codesigning trust chain
- Change `appstore cert rm` ID from a flag to a positional argument
- Fix missing `Content-Type` header on bundle ID registration request
The bxdiff command only had single-file mode. Implement batch mode
that iterates the OTA ZIP, finding BXDIFF patches in both
AssetData/payloadv2/patches/ and basesystem_patches/. Each patch
is extracted to a temp file, matched against a base file from the
--input folder, and applied via bxdiff50.Patch.
Closes#1161
macOS full OTAs can contain both arm64e and x86_64h system cryptex
files. The output path was the same for both, so the second one
overwrote the first. Extract the architecture from the cryptex
filename and use arch-specific subdirectories.
Closes#1162
iBridge IPSWs bundle firmware for 16+ T2 variants behind a single
URL. The URL deduplication kept only one device identifier, so
--decrypt only fetched keys for that device (~6% of files).
Collect all device identifiers per URL during dedup, then fetch
wiki keys for each identifier and merge them before matching.
Closes#1005