Repository navigation
fix(native): send iOS native-mode auth requests through NSURLSession - #475
Confidence 4/10 · 2 issues to address
🔴 Confidence 4/10 · risky as written. The host transport follows redirects the auth client explicitly forbids, and nothing tests the new routing; that security gap decides the number.
2 warnings −2 · tests missing −2 · risk high −1 · 0/1 new units observable −1
Fixes iOS native-mode sign-in by sending those requests through the host's NSURLSession instead of WebKit's fetch, which stamps Origin. The mechanism is sound, but the host follows redirects the auth transport forbids and none of the new path is tested.
globalThis.fetchhandsx-auth-mode: nativerequests to the host and answers from its replyhttp.rssends them with an ephemeral, cookielessNSURLSession, replying{id, status, headers, body}- The page gains
__hazel.replyso host replies reach the worker
Before merge
- Manual · Confirm sign-in on a physical TestFlight device before release; build 2970 shipped without it
Findings
🟠 Warning · F1 · Host path follows redirects the auth client forbids (redirect: "error")
security · apps/native/src/ios.ts:72
The auth runtime builds its client with redirect: "error" because the session travels in x-auth-request-session headers (apps/web-foldkit/src/platform/desktop-auth.ts:159). The payload sent to the host carries no redirect, and NSURLSession follows a redirect by default, so a 3xx re-sends those credential headers to the Location origin and the caller gets that response instead of a rejection.
Put `redirect: outgoing.redirect` in the payload, and have `http.rs` refuse the redirect (a task delegate answering `None`) so a 3xx surfaces as the load failure the client asked for.
🟠 Warning · F2 · New fetch routing and reply handling are covered by no test
tests · apps/native/src/ios.ts:62-63
apps/native/src tests its other global shims (shims.test.ts, and data-source.ts through offline-backend.test.ts), but nothing exercises this branch: a native request reaching the host, its id matching a late reply, a non-native request on WebKit's fetch, or { error } becoming a TypeError. The change's whole behavior is unverified in CI.
Extract the routing into `src/native-fetch.ts` taking the web fetch, `request` and a reply source, and test it: native routed, others passed through, an error reply throws.
Production impact
Production traffic of the changed files (last 7 days)
| File | Calls/day | Busiest operations |
|---|---|---|
apps/native/host/ios/src/http.rs |
586 | GET 330/day, 0.3% errGET 256/day, 3.0% err |
apps/native/src/ios.ts |
586 | GET 330/day, 0.3% errGET 256/day, 3.0% err |
What was checked
- Header name and value agree:
x-auth-modeset byOperationHttpClient, admitted asnativeatdesktop-login.ts:101 - The auth runtime's
FetchHttpClient.layerreadsglobalThis.fetchper request, so the override sees sign-in, session and sign-out - No tracer in
apps/native/src, so no client span was lost against the API's existing server span
Observability coverage: 0 of 1 changes observable
| Change | Kind | Observable | Evidence |
|---|---|---|---|
| native-mode HTTP request (worker → iOS host → API) | outbound call | no | No OpenTelemetry in apps/native/src; the call shows only as the API's server span |
e89d8fc · Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
Annotations
Check warning on line 72 in apps/native/src/ios.ts
maple-review-bot / Maple / review
security: Host path follows redirects the auth client forbids (`redirect: "error"`)
The auth runtime builds its client with `redirect: "error"` because the session travels in `x-auth-request-session` headers (`apps/web-foldkit/src/platform/desktop-auth.ts:159`). The payload sent to the host carries no `redirect`, and `NSURLSession` follows a redirect by default, so a 3xx re-sends those credential headers to the `Location` origin and the caller gets that response instead of a rejection.
Check warning on line 63 in apps/native/src/ios.ts
maple-review-bot / Maple / review
tests: New `fetch` routing and reply handling are covered by no test
`apps/native/src` tests its other global shims (`shims.test.ts`, and `data-source.ts` through `offline-backend.test.ts`), but nothing exercises this branch: a native request reaching the host, its `id` matching a late reply, a non-native request on WebKit's fetch, or `{ error }` becoming a `TypeError`. The change's whole behavior is unverified in CI.