Conversation
Since ~2026-09, Apple's GrandSlam authentication edge
(gsa.apple.com/grandslam/GsService2) rejects any request whose
X-MMe-Client-Info header contains the substring "com.apple.dt.Xcode"
with an immediate HTTP 503, regardless of User-Agent, request/response
plist content, or connection reuse.
This was independently reproduced with two direct requests against the
live endpoint, differing only in that header:
X-MMe-Client-Info containing "com.apple.dt.Xcode" -> 503 (blocked)
X-MMe-Client-Info containing "com.apple.akd" -> 401 (reaches
the real service)
Root cause and fix credited to altstoreio/AltStore#1790, which patched
AltStore's own (Swift) anisette code on macOS. AltServer-Linux doesn't
share that code - it fetches anisette data as JSON from an external
anisette server (see AnisetteDataManager::FetchAnisetteData), and the
X-MMe-Client-Info value returned by anisette servers commonly still
identifies as Xcode, tripping the same block.
This adds a small SanitizeClientInfo() helper that rewrites that one
substring at the single point anisette data enters this program, so
every caller that later forwards deviceDescription() as the
X-MMe-Client-Info header (there are four call sites across AltSign)
is covered without touching vendored AltSign code.
Verified end-to-end against a real device and Apple ID over several
days of testing: requests that previously failed with HTTP 503 before
ever reaching Apple's authentication logic now get a normal, structured
response.
Ben-Diehlci
pushed a commit
to Ben-Diehlci/altserver-linux
that referenced
this pull request
Sep 14, 2026
Both are on the path of the very first thing that will be run -- a hand-typed CLI install of AltStore.ipa -- so they are worth clearing before that attempt rather than debugging mid-bootstrap. 1. PR NyaMisty#135, X-MMe-Client-Info sanitization. Since ~2026-09 Apple's GSA edge rejects with an immediate 503 any request whose X-MMe-Client-Info contains "com.apple.dt.Xcode", and anisette servers commonly return exactly that -- upstream AltStore still builds one containing com.apple.dt.Xcode/3594.4.19 as of v2.3.3, confirmed in the local clone. Rewritten to com.apple.akd at the single point where anisette data enters the program. This is an unverified third-party claim that cannot be tested without a real Apple ID, and it alters a header Apple sees, so it is defeatable at runtime: ALTSERVER_NO_CLIENTINFO_SANITIZE=1 disables it. If sign-in fails with the rewrite in place, toggle that before blaming the anisette server. It also logs when it actually rewrites something, so the logs say which mode was in effect. 2. argv parsing in AltServerMain.cpp. `case 'a'` had no break and fell through into `case 'p'`, so `-a ID` set the password to ID as well. With the conventional `-u -a -p` ordering it works by accident because -p overwrites afterwards; with `-p PASS -a ID` the password silently becomes the Apple ID and sign-in fails with an unrelated-looking error. All five argv pointers were also uninitialised while udid/appleID/password are read unconditionally at the install call, making a missing flag undefined behaviour. And 'h' was handled in the switch but absent from the optstring, so -h printed "?? getopt returned character code 077 ??" before the usage text. Added a guard that names exactly which required flags are missing instead. Verified against a real build: -h prints usage cleanly; `-u X -a Y` with no -p now reports "Missing: --password", which is the direct proof that -a no longer sets it; all three flags together pass the guard. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ben-Diehlci
pushed a commit
to Ben-Diehlci/altserver-linux
that referenced
this pull request
Sep 14, 2026
…-bearing Phase 2 is up. The contract passes -- ten keys, all strings, HTTP 200, clock in sync -- and more importantly the volume mapping is proven rather than assumed: docker diff shows nothing identity-related on the container's writable layer, while adi.pb and device.json are present host-side. The lib/-only mount that the upstream README recommends was avoided, so a Portainer stack update will not destroy the machine identity. Records one result that retroactively justifies an earlier change: this server returns com.apple.dt.Xcode/3594.4.19 in X-MMe-Client-Info, which is exactly the substring Apple's GSA edge rejects with a 503. The PR NyaMisty#135 sanitizer applied in f2540f3 is therefore load-bearing for sign-in rather than speculative, and ALTSERVER_NO_CLIENTINFO_SANITIZE should stay unset. Also notes adi.pb is mode ---x-w-rwt, written that way by Apple's closed-source libCoreADI, so backups of it require sudo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ben-Diehlci
pushed a commit
to Ben-Diehlci/altserver-linux
that referenced
this pull request
Sep 14, 2026
…nst real Apple infra The com.apple.dt.Xcode -> com.apple.akd rewrite was applied on an unverified third-party claim from a PR opened two days earlier. It is now reproduced in both directions on this deployment, using the ALTSERVER_NO_CLIENTINFO_SANITIZE escape hatch added for exactly this purpose: sanitizer ON -> client-info says com.apple.akd -> first GSA request 200 sanitizer OFF -> client-info says com.apple.dt.Xcode -> first GSA request 503 So Apple really does reject anything carrying that substring, and the rewrite really does get past it. Keep it enabled. Worth reporting back on PR NyaMisty#135, whose author had only a curl repro. This also separates two problems that presented as one. The remaining failure is a 429 on the SECOND GSA request: unaffected by client-info, identical across two attempts 28 minutes apart, and present on the very first sign-in ever attempted from this machine -- so it is not cumulative volume throttling, which would be expected to move or escalate. Records the leading hypothesis while it is investigated: X-Apple-I-MD is a one-time password that regenerates per anisette fetch (observed directly -- two fetches 82 seconds apart returned different values), but FetchAnisetteData is called once and the result is used for BOTH GSA requests. The second request may therefore be replaying a consumed OTP. That fits every observation and would be fixable here rather than being an Apple-side wall. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ben-Diehlci
pushed a commit
to Ben-Diehlci/altserver-linux
that referenced
this pull request
Sep 14, 2026
…y#135 SLICE 2 of the setup portal. Pairing is where someone without background gets stuck, and its failure modes are unusually opaque, so the wizard's job is not to run commands -- it is to tell the three "nothing is showing up" cases apart: - tools missing, vs usbmuxd not running, vs no device on the cable - device present but LOCKED: `idevicepair validate` reports "a passcode is set", which reads like a permissions problem when it means "press the button" - device present but untrusted: needs `idevicepair pair` then TRUST on-device It states plainly that a USB cable is required exactly once and cannot be avoided (HAVE_WIRELESS_PAIRING is undefined in this build), while making clear that refresh afterwards is wireless -- which is the surprising part for a project whose whole point is wireless refresh. It also covers hypervisor USB passthrough, since on this deployment the VM is the likeliest reason a plugged-in phone never appears, and charge-only cables. Once paired it does not stop at "done": it prompts to back up /var/lib/lockdown and explains that BOTH files must be kept together, because restoring one without the other yields a mismatched HostID/SystemBUID that iOS rejects with the same generic error as every other lockdownd fault. Verified: all routes respond, and on a host without the tools the wizard blocks at step 1 rather than cascading misleading errors. Also drafts docs/pr135-confirmation.md -- a comment for upstream PR NyaMisty#135. That PR applied an unverified claim; this deployment reproduced it end-to-end in both directions against live Apple infrastructure (503 with com.apple.dt.Xcode present, 200 with it rewritten), which is materially stronger evidence than the curl repro currently on the PR. The draft is honest that sign-in still fails afterwards with an unrelated 429, so nobody concludes the patch is ineffective, and notes the misleading "invalid response" error that masks both. Checked to contain no Apple ID, UDID, machine identifier or hostname. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ben-Diehlci
pushed a commit
to Ben-Diehlci/altserver-linux
that referenced
this pull request
Sep 15, 2026
Both are on the path of the very first thing that will be run -- a hand-typed CLI install of AltStore.ipa -- so they are worth clearing before that attempt rather than debugging mid-bootstrap. 1. PR NyaMisty#135, X-MMe-Client-Info sanitization. Since ~2026-09 Apple's GSA edge rejects with an immediate 503 any request whose X-MMe-Client-Info contains "com.apple.dt.Xcode", and anisette servers commonly return exactly that -- upstream AltStore still builds one containing com.apple.dt.Xcode/3594.4.19 as of v2.3.3, confirmed in the local clone. Rewritten to com.apple.akd at the single point where anisette data enters the program. This is an unverified third-party claim that cannot be tested without a real Apple ID, and it alters a header Apple sees, so it is defeatable at runtime: ALTSERVER_NO_CLIENTINFO_SANITIZE=1 disables it. If sign-in fails with the rewrite in place, toggle that before blaming the anisette server. It also logs when it actually rewrites something, so the logs say which mode was in effect. 2. argv parsing in AltServerMain.cpp. `case 'a'` had no break and fell through into `case 'p'`, so `-a ID` set the password to ID as well. With the conventional `-u -a -p` ordering it works by accident because -p overwrites afterwards; with `-p PASS -a ID` the password silently becomes the Apple ID and sign-in fails with an unrelated-looking error. All five argv pointers were also uninitialised while udid/appleID/password are read unconditionally at the install call, making a missing flag undefined behaviour. And 'h' was handled in the switch but absent from the optstring, so -h printed "?? getopt returned character code 077 ??" before the usage text. Added a guard that names exactly which required flags are missing instead. Verified against a real build: -h prints usage cleanly; `-u X -a Y` with no -p now reports "Missing: --password", which is the direct proof that -a no longer sets it; all three flags together pass the guard. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ben-Diehlci
pushed a commit
to Ben-Diehlci/altserver-linux
that referenced
this pull request
Sep 15, 2026
…-bearing Phase 2 is up. The contract passes -- ten keys, all strings, HTTP 200, clock in sync -- and more importantly the volume mapping is proven rather than assumed: docker diff shows nothing identity-related on the container's writable layer, while adi.pb and device.json are present host-side. The lib/-only mount that the upstream README recommends was avoided, so a Portainer stack update will not destroy the machine identity. Records one result that retroactively justifies an earlier change: this server returns com.apple.dt.Xcode/3594.4.19 in X-MMe-Client-Info, which is exactly the substring Apple's GSA edge rejects with a 503. The PR NyaMisty#135 sanitizer applied in 04dd7ee is therefore load-bearing for sign-in rather than speculative, and ALTSERVER_NO_CLIENTINFO_SANITIZE should stay unset. Also notes adi.pb is mode ---x-w-rwt, written that way by Apple's closed-source libCoreADI, so backups of it require sudo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ben-Diehlci
pushed a commit
to Ben-Diehlci/altserver-linux
that referenced
this pull request
Sep 15, 2026
…nst real Apple infra The com.apple.dt.Xcode -> com.apple.akd rewrite was applied on an unverified third-party claim from a PR opened two days earlier. It is now reproduced in both directions on this deployment, using the ALTSERVER_NO_CLIENTINFO_SANITIZE escape hatch added for exactly this purpose: sanitizer ON -> client-info says com.apple.akd -> first GSA request 200 sanitizer OFF -> client-info says com.apple.dt.Xcode -> first GSA request 503 So Apple really does reject anything carrying that substring, and the rewrite really does get past it. Keep it enabled. Worth reporting back on PR NyaMisty#135, whose author had only a curl repro. This also separates two problems that presented as one. The remaining failure is a 429 on the SECOND GSA request: unaffected by client-info, identical across two attempts 28 minutes apart, and present on the very first sign-in ever attempted from this machine -- so it is not cumulative volume throttling, which would be expected to move or escalate. Records the leading hypothesis while it is investigated: X-Apple-I-MD is a one-time password that regenerates per anisette fetch (observed directly -- two fetches 82 seconds apart returned different values), but FetchAnisetteData is called once and the result is used for BOTH GSA requests. The second request may therefore be replaying a consumed OTP. That fits every observation and would be fixable here rather than being an Apple-side wall. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ben-Diehlci
pushed a commit
to Ben-Diehlci/altserver-linux
that referenced
this pull request
Sep 15, 2026
…y#135 SLICE 2 of the setup portal. Pairing is where someone without background gets stuck, and its failure modes are unusually opaque, so the wizard's job is not to run commands -- it is to tell the three "nothing is showing up" cases apart: - tools missing, vs usbmuxd not running, vs no device on the cable - device present but LOCKED: `idevicepair validate` reports "a passcode is set", which reads like a permissions problem when it means "press the button" - device present but untrusted: needs `idevicepair pair` then TRUST on-device It states plainly that a USB cable is required exactly once and cannot be avoided (HAVE_WIRELESS_PAIRING is undefined in this build), while making clear that refresh afterwards is wireless -- which is the surprising part for a project whose whole point is wireless refresh. It also covers hypervisor USB passthrough, since on this deployment the VM is the likeliest reason a plugged-in phone never appears, and charge-only cables. Once paired it does not stop at "done": it prompts to back up /var/lib/lockdown and explains that BOTH files must be kept together, because restoring one without the other yields a mismatched HostID/SystemBUID that iOS rejects with the same generic error as every other lockdownd fault. Verified: all routes respond, and on a host without the tools the wizard blocks at step 1 rather than cascading misleading errors. Also drafts docs/pr135-confirmation.md -- a comment for upstream PR NyaMisty#135. That PR applied an unverified claim; this deployment reproduced it end-to-end in both directions against live Apple infrastructure (503 with com.apple.dt.Xcode present, 200 with it rewritten), which is materially stronger evidence than the curl repro currently on the PR. The draft is honest that sign-in still fails afterwards with an unrelated 429, so nobody concludes the patch is ineffective, and notes the misleading "invalid response" error that masks both. Checked to contain no Apple ID, UDID, machine identifier or hostname. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Problem
Since ~early September 2026, every Apple ID sign-in through this project fails
with an HTTP 503 from
gsa.apple.com/grandslam/GsService2, before Apple'sauthentication logic is ever reached.
Root cause
Credit for the actual root cause goes to
altstoreio/AltStore#1790:
Apple's GSA edge rejects any request whose
X-MMe-Client-Infoheadercontains the substring
com.apple.dt.Xcode, independent of version,User-Agent, or connection reuse. That PR fixed it for AltStore's own (Swift,
macOS) anisette code.
This project doesn't share that code — it fetches anisette data as JSON from
an external anisette server (
AnisetteDataManager::FetchAnisetteData), andthe
X-MMe-Client-Infovalue such servers commonly return still identifiesas Xcode, tripping the same block. I confirmed this independently with two
otherwise-identical requests directly against the live endpoint:
Fix
Adds a small
SanitizeClientInfo()helper inAnisetteDataManager.cppthatrewrites that one substring at the single point anisette data enters this
program (right when the anisette server's JSON response is parsed), so every
downstream call site in AltSign that later forwards
anisetteData->deviceDescription()as theX-MMe-Client-Infoheader (thereare four of them) is covered without needing to touch vendored AltSign code
at all.
This is intentionally scoped to just this one issue. It does not include
the separate, already-known GrandSlam "reuse the same connection for 3
requests" fix (AltSign#52 /
#47), since that lives in
the vendored
AltSignsubmodule rather than this project's own code, andwould need a different approach (e.g. extending
rewrite_altsign_source.py) to contribute cleanly. Happy to follow up withthat separately if useful.
Testing
Verified end-to-end against a real iPhone and a real Apple ID over several
days of testing (no device or account details included here). Before this
change, GrandSlam requests failed with HTTP 503 on the very first request.
After it, requests reach Apple's authentication service normally (structured
200/401 responses instead of an opaque 503 HTML page), and a full
sign-in + IPA install completes successfully.
Not tested on 32-bit ARM/x86 builds, only x86_64.