{"record":{"id":"0f7fca25a40bd4e7","repo":"paperclipai/paperclip","slug":"networkallowlist-index-must-use-an-exact-hostn","errorCode":null,"errorMessage":"networkAllowlist[${index}] must use an exact hostname; wildcards are not supported.","messagePattern":"networkAllowlist\\[(.+?)\\] must use an exact hostname; wildcards are not supported\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/adapter-utils/src/local-process-sandbox.ts","lineNumber":137,"sourceCode":"}\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;\n  if (value === \"deny\" || value === \"allowlist\") return value;\n  throw new Error('networkScope must be \"deny\" or \"allowlist\".');\n}","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/adapter-utils/src/local-process-sandbox.ts#L119-L155","documentation":"Thrown by parseNetworkAllowlistEntry when the parsed hostname is empty, is exactly '*', or starts with '*.'. The sandbox network allowlist requires exact hostnames for security — wildcard matching would broaden network egress beyond what the operator intended, so it is explicitly rejected.","triggerScenarios":"Calling parseLocalProcessNetworkAllowlist with an entry like '*' (match all), '*.example.com' (wildcard subdomain), or an entry whose URL hostname resolves to empty after parsing.","commonSituations":"A developer tries to allow all subdomains with '*.example.com' expecting glob-style matching; a config template uses '*' as a placeholder that was never replaced; an entry like 'https://:443' produces an empty hostname.","solutions":["List each exact hostname individually instead of using wildcards.","If subdomain matching is needed, enumerate all subdomains or use a more specific pattern that resolves to exact hostnames.","Replace any '*' placeholder values in configuration templates with concrete hostnames before deployment."],"exampleFix":"// before\nconst allowlist = [\"*.example.com\"];\n// after\nconst allowlist = [\"api.example.com\", \"www.example.com\", \"cdn.example.com\"];","handlingStrategy":"validation","validationCode":"function hasNoWildcards(hostname: string): boolean {\n  const trimmed = hostname.trim().toLowerCase();\n  return trimmed.length > 0 && trimmed !== \"*\" && !trimmed.startsWith(\"*.\");\n}\nconst allExact = allowlist.every(hasNoWildcards);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Enumerate exact hostnames instead of using wildcards.","Replace placeholder '*' values in config templates with concrete hostnames before deployment.","Document the exact-hostname-only policy in the sandbox configuration guide."],"tags":["validation","network","sandbox","security","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"}