Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,17 @@ public struct AlibabaTokenPlanUsageFetcher: Sendable {
request.setValue(
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
forHTTPHeaderField: "Accept")
// The OneConsole shell only server-renders `window.ALIYUN_CONSOLE_CONFIG.SEC_TOKEN` for a
// genuine same-origin document navigation; a bare request receives a token-less shell, so the
// Personal `sec_token` can never be scraped. Send the browser-navigation headers so the shell
// includes it (mainland Personal/Solo rejects the API without it — fixes #2500/#2349/#2370).
if let origin = request.url.flatMap(\.host).map({ "https://\($0)/" }) {
request.setValue(origin, forHTTPHeaderField: "Referer")
Comment on lines +547 to +548

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve non-default ports in the shell Referer

When ALIBABA_TOKEN_PLAN_HOST contains a supported non-default port, such as the :9443 override already exercised in AlibabaTokenPlanProviderTests, URL.host drops that port and produces Referer: https://alibaba-token-plan.test/ for a request to https://alibaba-token-plan.test:9443/.... Those are different origins, so a shell that verifies the claimed same-origin navigation can remain token-less and defeat the new scrape; construct the Referer from the request URL's scheme, host, and port instead.

Useful? React with 👍 / 👎.

}
request.setValue("same-origin", forHTTPHeaderField: "Sec-Fetch-Site")
request.setValue("navigate", forHTTPHeaderField: "Sec-Fetch-Mode")
request.setValue("document", forHTTPHeaderField: "Sec-Fetch-Dest")
request.setValue("zh-CN,zh;q=0.9,en;q=0.8", forHTTPHeaderField: "Accept-Language")

if let (data, response) = try? await session.data(for: request),
let httpResponse = response as? HTTPURLResponse,
Expand Down Expand Up @@ -1257,12 +1268,15 @@ public struct AlibabaTokenPlanUsageFetcher: Sendable {
return names.isEmpty ? "none" : names.joined(separator: ",")
}

private static func extractSECToken(from html: String) -> String? {
static func extractSECToken(from html: String) -> String? {
let patterns = [
#""secToken"\s*:\s*"([^"]+)""#,
#""sec_token"\s*:\s*"([^"]+)""#,
#"secToken['"]?\s*[:=]\s*['"]([^'"]+)['"]"#,
#"sec_token['"]?\s*[:=]\s*['"]([^'"]+)['"]"#,
// Aliyun's OneConsole shell embeds it inside `window.ALIYUN_CONSOLE_CONFIG` with an
// upper-case, unquoted key: `SEC_TOKEN: "<token>"`. The lower-case patterns above miss it.
#"SEC_TOKEN['"]?\s*[:=]\s*['"]([^'"]+)['"]"#,
]
for pattern in patterns {
if let token = self.matchFirstGroup(pattern: pattern, in: html), !token.isEmpty {
Expand Down
31 changes: 31 additions & 0 deletions Tests/CodexBarTests/AlibabaTokenPlanProviderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1313,3 +1313,34 @@ final class AlibabaTokenPlanStubURLProtocol: URLProtocol {

override func stopLoading() {}
}

struct AlibabaTokenPlanSECTokenScrapeTests {
@Test
func `extracts the OneConsole SEC_TOKEN embedded in the dashboard shell`() {
// The aliyun OneConsole shell embeds the token as an upper-case, unquoted key inside
// `window.ALIYUN_CONSOLE_CONFIG` — the shape the mainland Personal/Solo gateway requires.
let html = """
<script>
window.ALIYUN_CONSOLE_CONFIG = {
LANG: "zh",
SEC_TOKEN: "NwsiCAv9SDsHsNab4Jexample",
ACCOUNT_NAME: "someone"
};
</script>
"""
#expect(AlibabaTokenPlanUsageFetcher.extractSECToken(from: html) == "NwsiCAv9SDsHsNab4Jexample")
}

@Test
func `still extracts the lower-case secToken and sec_token shapes`() {
#expect(
AlibabaTokenPlanUsageFetcher.extractSECToken(from: #"{"secToken":"abc123"}"#) == "abc123")
#expect(
AlibabaTokenPlanUsageFetcher.extractSECToken(from: #"var x = { sec_token: 'def456' };"#) == "def456")
}

@Test
func `returns nil when no token is present`() {
#expect(AlibabaTokenPlanUsageFetcher.extractSECToken(from: "<html><body>no token here</body></html>") == nil)
}
}