{"record":{"id":"86d3631dc99cd9f4","repo":"paperclipai/paperclip","slug":"networkallowlist-index-must-be-a-hostname-hos","errorCode":null,"errorMessage":"networkAllowlist[${index}] must be a hostname, hostname:port, or origin URL.","messagePattern":"networkAllowlist\\[(.+?)\\] must be a hostname, hostname:port, or origin URL\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/adapter-utils/src/local-process-sandbox.ts","lineNumber":134,"sourceCode":"  const realCommand = await fs.realpath(command).catch(() => command);\n  paths.add(await nearestPackageRoot(realCommand));\n  return Array.from(paths);\n}\n\nfunction parseNetworkAllowlistEntry(entry: string, index: number): NetworkAllowlistRule {\n  const trimmed = entry.trim();\n  if (!trimmed) throw new Error(`networkAllowlist[${index}] must not be empty.`);\n  let hostname: string;\n  let port: string | null;\n  try {\n    const parsed = new URL(trimmed.includes(\"://\") ? trimmed : `https://${trimmed}`);\n    if (parsed.username || parsed.password || parsed.pathname !== \"/\" || parsed.search || parsed.hash) {\n      throw new Error(\"path\");\n    }\n    hostname = parsed.hostname.toLowerCase();\n    port = parsed.port || null;\n  } catch {\n    throw new Error(`networkAllowlist[${index}] must be a hostname, hostname:port, or origin URL.`);\n  }\n  if (!hostname || hostname === \"*\" || hostname.startsWith(\"*.\")) {\n    throw new Error(`networkAllowlist[${index}] must use an exact hostname; wildcards are not supported.`);\n  }\n  return { hostname, port };\n}\n\nexport function parseLocalProcessNetworkAllowlist(value: unknown): string[] {\n  if (!Array.isArray(value)) return [];\n  return value.map((entry, index) => {\n    if (typeof entry !== \"string\") throw new Error(`networkAllowlist[${index}] must be a string.`);\n    const rule = parseNetworkAllowlistEntry(entry, index);\n    return rule.port ? `${rule.hostname}:${rule.port}` : rule.hostname;\n  });\n}\n\nexport function parseLocalProcessNetworkScope(value: unknown): LocalProcessNetworkScope | null {\n  if (value == null || value === \"\") return null;","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/adapter-utils/src/local-process-sandbox.ts#L116-L152","documentation":"Thrown by parseNetworkAllowlistEntry when an entry cannot be parsed as a hostname, hostname:port, or origin URL. The function prepends 'https://' if no scheme is present, then constructs a URL; if URL parsing throws, or if the entry contains a path, username/password, query string, or fragment, this error fires.","triggerScenarios":"Calling parseLocalProcessNetworkAllowlist with an entry like 'example.com/api' (has a path), 'user:pass@example.com' (has credentials), 'example.com?q=1' (has query), or a completely malformed string like 'not a url'. The URL constructor or the path/credential checks reject it.","commonSituations":"An entry includes a full API path instead of just the origin ('https://api.example.com/v1/endpoint' instead of 'api.example.com'); credentials embedded in the URL; query parameters in the allowlist entry; a typo or non-URL string in the config.","solutions":["Use only bare hostnames ('example.com'), hostname:port ('example.com:443'), or origin URLs ('https://example.com') in the allowlist.","Strip paths, query strings, fragments, and credentials from entries before adding them to the allowlist.","Validate entries with parseLocalProcessNetworkAllowlist during configuration loading."],"exampleFix":"// before\nconst allowlist = [\"https://api.example.com/v1/chat\"];\n// after\nconst allowlist = [\"api.example.com\"];","handlingStrategy":"validation","validationCode":"function validateAllowlistEntry(entry: string): boolean {\n  const trimmed = entry.trim();\n  if (!trimmed) return false;\n  try {\n    const parsed = new URL(trimmed.includes(\"://\") ? trimmed : `https://${trimmed}`);\n    return !parsed.username && !parsed.password && parsed.pathname === \"/\" && !parsed.search && !parsed.hash;\n  } catch {\n    return false;\n  }\n}\nconst allValid = allowlist.every(validateAllowlistEntry);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use only bare hostnames or hostname:port pairs in the allowlist.","Strip paths, query strings, and credentials from entries before adding them.","Validate allowlist entries during configuration loading with parseLocalProcessNetworkAllowlist."],"tags":["validation","network","sandbox","local-process-sandbox","adapter-utils"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}