{"record":{"id":"6b3554626473d9ab","repo":"remix-run/react-router","slug":"origin-header-is-not-a-valid-url-aborting-the-a","errorCode":null,"errorMessage":"`origin` header is not a valid URL. Aborting the action.","messagePattern":"`origin` header is not a valid URL\\. Aborting the action\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router/lib/actions.ts","lineNumber":14,"sourceCode":"export function throwIfPotentialCSRFAttack(\n  request: Request,\n  allowedActionOrigins: string[] | undefined,\n) {\n  let originHeader = request.headers.get(\"origin\");\n  let originDomain: string | null = null;\n\n  try {\n    originDomain =\n      typeof originHeader === \"string\" && originHeader !== \"null\"\n        ? new URL(originHeader).host\n        : originHeader;\n  } catch {\n    throw new Error(\n      `\\`origin\\` header is not a valid URL. Aborting the action.`,\n    );\n  }\n  let host = new URL(request.url).host;\n\n  if (originDomain && originDomain !== host) {\n    if (!isAllowedOrigin(originDomain, allowedActionOrigins)) {\n      // This seems to be an CSRF attack. We should not proceed with the action.\n      throw new Error(\n        \"The `request.url` host does not match `origin` header from a forwarded \" +\n          \"action request. Aborting the action.\",\n      );\n    }\n  }\n}\n\n// Implementation of micromatch by Next.js https://github.com/vercel/next.js/blob/ea927b583d24f42e538001bf13370e38c91d17bf/packages/next/src/server/app-render/csrf-protection.ts#L6\nfunction matchWildcardDomain(domain: string, pattern: string) {","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/remix-run/react-router/blob/1fd704a7dabcbe3ae09d7387b460e6acaba30ec1/packages/react-router/lib/actions.ts#L1-L32","documentation":"Thrown by `throwIfPotentialCSRFAttack` when the `Origin` request header is a non-`null` string that cannot be parsed by `new URL(originHeader)`. The library aborts the action because it cannot safely classify the request as same-origin or cross-origin.","triggerScenarios":"A mutation request (POST/PUT/PATCH/DELETE) reaches a React Router action with an `Origin` header value that is not a valid URL and not the literal string `null`. Examples: a malformed proxy header, `Origin: //`, or a custom client setting garbage in Origin.","commonSituations":"Misconfigured reverse proxy rewriting/stripping Origin; a CDN injecting a malformed Origin; a security scanner or curl invocation sending `Origin: foo`; non-browser clients that set Origin to a non-URL token.","solutions":["Inspect the raw `Origin` header the client is actually sending (browser devtools, proxy access logs).","Fix the upstream proxy/client so Origin is either a well-formed absolute URL or omitted/`null`.","If you control the client, send `Origin: https://your-app.example` or omit the header rather than send garbage.","Reproduce with curl `-H 'Origin: https://valid.example'` to confirm the action succeeds once the header is well-formed."],"exampleFix":"# before\ncurl -X POST https://app/api -H 'Origin: ///'\n\n# after\ncurl -X POST https://app/api -H 'Origin: https://app.example'","handlingStrategy":"validation","validationCode":"function isValidOriginHeader(h: string | null): boolean {\n  if (h === null || h === 'null') return true;\n  try { new URL(h); return true; } catch { return false; }\n}\n// in your proxy/edge, sanitize before forwarding:\nif (!isValidOriginHeader(request.headers.get('origin'))) {\n  return new Response('Bad Origin', { status: 400 });\n}","typeGuard":"function isParsableOrigin(h: string | null | undefined): h is string {\n  if (!h || h === 'null') return false;\n  try { new URL(h); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  await action({ request });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('`origin` header is not a valid URL')) {\n    return new Response('Invalid Origin header', { status: 400 });\n  }\n  throw e;\n}","preventionTips":["Ensure reverse proxies forward `Origin` verbatim from the browser.","Validate Origin at your edge before it reaches the app.","Document for API clients that Origin must be a valid absolute URL or omitted."],"tags":["csrf","actions","security","headers"],"backgroundTag":null,"analyzedSha":"1fd704a7dabcbe3ae09d7387b460e6acaba30ec1","analyzedAt":"2026-08-12T13:54:57.804Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}