commit 52847a9fa10d2a16f5c1bfcc8f60ce0d83738ac9
parent 616df25068762910884dc8bb94e67d6edc05d961
Author: Michael Camilleri <[email protected]>
Date: Sat, 18 Jul 2026 08:47:30 +0900
Require HTTPS before forwarding the cookies
When determining the signed-in account email, NYTAuthService scrapes
gqlUrlClient out of the account-page HTML and posts the full cookie
header to whatever URL it finds, without checking its scheme. A
malformed or misconfigured value could therefore direct the session
cookie over cleartext HTTP, exposing it to any network observer.
This commit rejects a non-HTTPS gqlUrlClient during configuration
extraction, so the request is never built and the flow degrades to the
existing no-email path.
Co-Authored-By: Claude Fable 5 <[email protected]>
Diffstat:
2 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/Crossmate/Services/NYTAuthService.swift b/Crossmate/Services/NYTAuthService.swift
@@ -275,6 +275,7 @@ final class NYTAuthService {
) -> AccountGraphQLConfiguration? {
guard let urlString = firstJSONStringValue(named: "gqlUrlClient", in: html),
let url = URL(string: urlString),
+ url.scheme?.lowercased() == "https",
let appType = firstJSONStringValue(named: "nyt-app-type", in: html),
let appVersion = firstJSONStringValue(named: "nyt-app-version", in: html),
let token = firstJSONStringValue(named: "nyt-token", in: html) else {
diff --git a/Tests/Unit/NYTAuthServiceTests.swift b/Tests/Unit/NYTAuthServiceTests.swift
@@ -84,4 +84,44 @@ struct NYTAuthServiceTests {
#expect(configuration?.headers["nyt-app-version"] == "0.0.5")
#expect(configuration?.headers["nyt-token"] == "abc/123")
}
+
+ @Test("Rejects non-HTTPS GraphQL endpoint in account page HTML")
+ func rejectsNonHTTPSGraphQLEndpoint() throws {
+ let html = #"""
+ <script>
+ window.__preloadedData = {
+ "config": {
+ "gqlUrlClient": "http://samizdat-graphql.nytimes.com/graphql/v2",
+ "gqlRequestHeaders": {
+ "nyt-app-type": "project-vi",
+ "nyt-app-version": "0.0.5",
+ "nyt-token": "abc/123"
+ }
+ }
+ }
+ </script>
+ """#
+
+ #expect(NYTAuthService.extractAccountGraphQLConfiguration(from: html) == nil)
+ }
+
+ @Test("Rejects schemeless GraphQL endpoint in account page HTML")
+ func rejectsSchemelessGraphQLEndpoint() throws {
+ let html = #"""
+ <script>
+ window.__preloadedData = {
+ "config": {
+ "gqlUrlClient": "/graphql/v2",
+ "gqlRequestHeaders": {
+ "nyt-app-type": "project-vi",
+ "nyt-app-version": "0.0.5",
+ "nyt-token": "abc/123"
+ }
+ }
+ }
+ </script>
+ """#
+
+ #expect(NYTAuthService.extractAccountGraphQLConfiguration(from: html) == nil)
+ }
}