{"record":{"id":"337fe09b310fd3cf","repo":"remix-run/remix","slug":"trusted-origin-must-not-be-empty","errorCode":null,"errorMessage":"trusted origin must not be empty","messagePattern":"trusted origin must not be empty","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cop-middleware/src/lib/cop.ts","lineNumber":177,"sourceCode":"  }\n\n  return 'Forbidden: cross-origin request detected, and/or browser is out of date: Sec-Fetch-Site is missing, and Origin does not match Host'\n}\n\nfunction getHeaderValue(headers: Headers, name: string): string | null {\n  let value = headers.get(name)\n  if (value == null) {\n    return null\n  }\n\n  let trimmedValue = value.trim()\n  return trimmedValue === '' ? null : trimmedValue\n}\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)","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/cop-middleware/src/lib/cop.ts#L159-L195","documentation":"The COP (cross-origin policy) middleware validates each trusted origin; after trimming, an empty string is rejected because an empty origin is never a meaningful trust grant.","triggerScenarios":"Calling addTrustedOrigin('') or a whitespace-only string such as '   ', or configuration that reads an unset env var into the origins list.","commonSituations":"`addTrustedOrigin(process.env.TRUSTED_ORIGIN ?? '')` when the var is unset; looping over a config array that contains an empty entry; copy-paste placeholders left in config.","solutions":["Skip empty values before adding: filter origins with `.filter(o => o.trim() !== '')`","Set the env var to the full origin (e.g. https://api.example.com)","Default to a real origin instead of '' when the env var is missing"],"exampleFix":"// before\ncop.addTrustedOrigin(process.env.TRUSTED_ORIGIN ?? '')\n// after\nlet origin = process.env.TRUSTED_ORIGIN\nif (origin) cop.addTrustedOrigin(origin)","handlingStrategy":"validation","validationCode":"origins.filter(o => o.trim() !== '').forEach(o => cop.addTrustedOrigin(o))","typeGuard":"function isNonEmptyString(v: unknown): v is string {\n  return typeof v === 'string' && v.trim() !== ''\n}","tryCatchPattern":null,"preventionTips":["Guard env-var-driven config with truthiness checks","Filter config arrays for empty entries","Fail fast at startup with a clear config error"],"tags":["cop-middleware","security","origin","validation"],"backgroundTag":"invalid-origin-config","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}