From 769546a0f327d8c9cbd604b687eb5bbb87466632 Mon Sep 17 00:00:00 2001 From: Rogue911 Date: Sat, 12 Sep 2026 16:39:41 +0200 Subject: [PATCH] Sanitize X-MMe-Client-Info to avoid Apple's Xcode-based GSA block 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. Co-Authored-By: Claude Sonnet 5 --- src/AnisetteDataManager.cpp | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/AnisetteDataManager.cpp b/src/AnisetteDataManager.cpp index 84ba608..9617d2c 100644 --- a/src/AnisetteDataManager.cpp +++ b/src/AnisetteDataManager.cpp @@ -13,6 +13,30 @@ #define odslog(msg) { std::stringstream ss; ss << msg << std::endl; OutputDebugStringA(ss.str().c_str()); } +// Since ~2026-09, Apple's GSA edge (gsa.apple.com/grandslam/GsService2) rejects with an +// immediate HTTP 503 any request whose "X-MMe-Client-Info" header contains the substring +// "com.apple.dt.Xcode" - independent of version, User-Agent, or connection reuse. This was +// confirmed here with a direct curl repro (with vs. without the substring: 503 vs 401, i.e. +// actually reaching the auth service), matching altstoreio/AltStore PR #1790's findings. +// Our anisette server (ani.sidestore.io) reports a client-info string containing exactly +// that substring, so we sanitize it once here, at the single point where anisette data +// enters this program, before it's ever used to build a request header. +// See: https://github.com/altstoreio/AltStore/pull/1790 +static std::string SanitizeClientInfo(std::string clientInfo) +{ + const std::string needle = "com.apple.dt.Xcode"; + const std::string replacement = "com.apple.akd"; + + size_t pos = 0; + while ((pos = clientInfo.find(needle, pos)) != std::string::npos) + { + clientInfo.replace(pos, needle.length(), replacement); + pos += replacement.length(); + } + + return clientInfo; +} + AnisetteDataManager* AnisetteDataManager::_instance = nullptr; AnisetteDataManager* AnisetteDataManager::instance() @@ -133,7 +157,7 @@ std::shared_ptr AnisetteDataManager::FetchAnisetteData() std::atoi(jsonVal.at("X-Apple-I-MD-RINFO").as_string().c_str()), jsonVal.at("X-Mme-Device-Id").as_string(), jsonVal.at("X-Apple-I-SRL-NO").as_string(), - jsonVal.at("X-MMe-Client-Info").as_string(), + SanitizeClientInfo(jsonVal.at("X-MMe-Client-Info").as_string()), tv, jsonVal.at("X-Apple-Locale").as_string(), jsonVal.at("X-Apple-I-TimeZone").as_string());