Preserve Apple errors while retrying transient GrandSlam failures - #53
Open
ahmed-raza-shaikh wants to merge 1 commit into
Open
Preserve Apple errors while retrying transient GrandSlam failures#53ahmed-raza-shaikh wants to merge 1 commit into
ahmed-raza-shaikh wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GrandSlam sometimes returns an HTML error page during Apple ID sign-in. AltSign feeds that page to the property-list parser, so a transport/server failure appears as
NSCocoaErrorDomain 3840/Encountered unknown tag html. This change uses the modern AuthKit User-Agent and an isolated session for each GSA attempt, adds bounded recovery for unstructured HTTP 5xx responses, and preserves Apple's structured protocol results before considering retries.This is a source-and-tests contribution against
notarized, the line used by AltStore Classic. The companion AltStore integration PR #1786 consumes this dependency change.Background
Existing work and why this proposal exists
This builds on existing investigations, rather than claiming the original discovery:
The additional reviewable pieces here are a monotonic time budget, protocol-result precedence over HTTP status, body-free error handling, and 17 executable regression scenarios. If maintainers prefer to fold these changes into #50/#51/#52 rather than merge another proposal, that would also address the goal. The existing proposals are still open; this PR does not imply they were merged or authored here.
Failure mechanism and evidence
The sign-in sequence sends SRP
init, SRPcomplete, andapptokensrequests throughsendAuthenticationRequest. The original investigation observed a reused connection return two plist responses followed by an HTML 503. A later real installation attempt also produced a 503 after the per-request-session workaround was already installed. That latter observation is why this contribution adds bounded retries instead of assuming isolation alone guarantees success.A local, credential-free HTTP/1.1 fixture independently reproduced the original failure: its first two requests on a connection return valid plists and subsequent requests return HTML 503. The original production method failed on the third exchange with Cocoa error 3840; the isolated-session method completed all three exchanges on separate connections. This proves the client behavior under that failure condition; it does not claim knowledge of Apple's internal load-balancer implementation or a universal two-request limit.
Changes
Isolate GSA transport and bound recovery
sendAuthenticationRequestcontinues to construct the same request body and headers, with the GSA User-Agent changed to the value proposed in #47. It delegates execution to a privatesendGrandSlamRequesthelper.Each attempt:
ProcessInfo.systemUptime.Response.Statusplist using the existing Apple error/success semantics.The policy is five total attempts, with delays of 1, 2, 4, and 8 seconds, constrained by 20 seconds per GSA exchange. A retry is not scheduled if its delay would exhaust the budget. This deadline is a deliberate operational bound, not a claim about the undocumented lifetime of anisette data; maintainer input on the budget is welcome.
Preserve protocol results
A structured Apple result takes precedence over the HTTP envelope. This preserves existing behavior for success and authentication challenges, including HTTP 409 with
ec = 0, and avoids retrying real credential or anisette failures returned inside HTTP 503.Existing mappings remain intact:
-20101/-22406-22421ecwithemResponse.Statuswith zero or absentecThe SRP payloads, key derivation, anisette generation, developer-portal requests, and two-factor code submission flows are unchanged. A 5xx response is not assumed to prove that Apple did not process the request.
Avoid leaking error-page contents
When an unusable response cannot be recovered, the user receives
URLError.badServerResponsewith the HTTP status when available. Neither the response body nor the property-list parser's underlying error is included. This avoids both the misleading format-error message and accidental disclosure of body content through an error object.Testing
Added:
Tests/GrandSlamTransport/test_transport.pyTests/GrandSlamTransport/README.mdRun on macOS with Python 3 and Xcode command-line tools:
The harness extracts the production Swift methods, changes only the endpoint to loopback, and compiles them with minimal model/error shims. A test-only URLProtocol injects cancellation and offline failures. No Apple account, certificate, password, verification code, or external authentication endpoint is used.
Result: all 17 scenarios passed. The persistent-503 case made exactly five attempts over approximately 16.1 seconds, within the 20-second budget. All fixture requests used separate connections, and every case observed one completion.
Coverage includes 503 recovery/exhaustion, 1/2/4/8 backoff, structured Apple errors on both 200 and 503, challenges/success on non-2xx responses, malformed HTML/array responses, cancellation/offline passthrough, in-flight timeout, insufficient/expired budgets, modern User-Agent, and absence of body/parser-error leakage. The global staged-file Semgrep and high-severity Bandit checks also passed.
Verification boundary
27f118687765b51fec0085d730d49b51943042624752c05ed084314ad7a388e6). The final PR source also has a fresh passing transport-suite run. This fixture tests macOS Foundation transport behavior, not live SRP or the actual numeric implementation of the shimmed error type._alt_*corecrypto symbols normally provided by the workspace's separately built crypto library. Neither attempt is counted as a passing standalone package build. The successful recovery application builds used the Xcode workspace setup.Additional Notes
Deployment
AltSign is compiled into both sides of the Classic workflow. Rebuilding AltServer alone does not update the copy used by an existing iPhone installation. Consumers need coordinated Mac/iPhone builds and distribution of the patched iPhone IPA; otherwise the original format error can remain on-device.
This PR contains source and a local test harness only. It does not publish signed apps, signing identities, provisioning profiles, or raw device logs. It was prepared with AI assistance, reviewed against the production flow and upstream discussions, and validated with executed tests plus the reporter's explicit on-device confirmation.