{"record":{"id":"3fae88c552dd45ff","repo":"remix-run/remix","slug":"invalid-origin-json-stringify-origin-path-qu","errorCode":null,"errorMessage":"invalid origin ${JSON.stringify(origin)}: path, query, and fragment are not allowed","messagePattern":"invalid origin (.+?): path, query, and fragment are not allowed","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cop-middleware/src/lib/cop.ts","lineNumber":190,"sourceCode":"}\n\nfunction validateTrustedOrigin(origin: string): string {\n  let trimmedOrigin = origin.trim()\n  if (trimmedOrigin === '') {\n    throw new Error('trusted origin must not be empty')\n  }\n\n  if (trimmedOrigin.endsWith('/')) {\n    throw new Error(`invalid origin ${JSON.stringify(origin)}: trailing slash is not allowed`)\n  }\n\n  let parsedOrigin = parseOrigin(trimmedOrigin)\n  if (parsedOrigin == null) {\n    throw new Error(`invalid origin ${JSON.stringify(origin)}`)\n  }\n\n  if (parsedOrigin.pathname !== '/' || parsedOrigin.search !== '' || parsedOrigin.hash !== '') {\n    throw new Error(\n      `invalid origin ${JSON.stringify(origin)}: path, query, and fragment are not allowed`,\n    )\n  }\n\n  return serializeOrigin(parsedOrigin)\n}\n\nfunction normalizeOrigin(origin: string): string | null {\n  let parsedOrigin = parseOrigin(origin)\n  return parsedOrigin == null ? null : serializeOrigin(parsedOrigin)\n}\n\nfunction parseOrigin(origin: string): URL | null {\n  try {\n    let parsedOrigin = new URL(origin)\n    if (parsedOrigin.host === '') {\n      return null\n    }","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/cop-middleware/src/lib/cop.ts#L172-L208","documentation":"A trusted origin must be exactly scheme://host — no path, query string, or fragment. Including any of these component makes the value not an origin, so it is rejected with this message.","triggerScenarios":"addTrustedOrigin('https://example.com/api'), 'https://example.com?token=1', or 'https://example.com#section'.","commonSituations":"Trusting a specific API endpoint URL instead of its origin; copy-pasting deep links; scoping trust with path patterns (not supported — use bypass patterns for path-scoped rules).","solutions":["Trim the value to scheme://host, e.g. 'https://example.com'","Use addInsecureBypassPattern('GET /api/*') for path-scoped exceptions instead of encoding paths in origins","Document in config examples that origins are scheme+host only"],"exampleFix":"// before\ncop.addTrustedOrigin('https://example.com/api')\n// after\ncop.addTrustedOrigin('https://example.com')\ncop.addInsecureBypassPattern('GET /api/*')","handlingStrategy":"validation","validationCode":"let u = new URL(origin)\nif (u.pathname !== '/' || u.search || u.hash) throw new Error('origin must be scheme://host')\n// or strip: cop.addTrustedOrigin(`${u.protocol}//${u.host}`)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Trust origins, not endpoint URLs","Use bypass patterns for path-scoped exceptions","Document the scheme://host-only rule in config templates"],"tags":["cop-middleware","security","origin","url-parsing"],"backgroundTag":"invalid-origin-config","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}