{"record":{"id":"d0f3d857601d96cb","repo":"iflytek/astron-agent","slug":"invalid-private-endpoint-allow-list-entry","errorCode":null,"errorMessage":"Invalid PRIVATE_ENDPOINT_ALLOW_LIST entry","messagePattern":"Invalid PRIVATE_ENDPOINT_ALLOW_LIST entry","errorType":"validation","errorClass":"OutboundPolicyError","httpStatus":null,"severity":"error","filePath":"core/plugin/link/infra/tool_exector/ssrf_guard.py","lineNumber":259,"sourceCode":"            # Use the same IDNA normalization as aiohttp/yarl applies to request hosts.\n            # Python's built-in ``idna`` codec follows IDNA2003 and would otherwise\n            # collapse distinct hosts such as faß.de and fass.de.\n            domains.append(_normalize_hostname(value))\n        except OutboundPolicyError as exc:\n            raise OutboundPolicyError(\"Invalid DOMAIN_BLACK_LIST entry\") from exc\n    return tuple(domains)\n\n\ndef _parse_private_endpoints(raw_value: str) -> Tuple[Endpoint, ...]:\n    endpoints = []\n    for entry in raw_value.split(\",\"):\n        value = entry.strip()\n        if not value:\n            continue\n        try:\n            parsed = _parse_http_url(value)\n        except OutboundPolicyError as exc:\n            raise OutboundPolicyError(\n                \"Invalid PRIVATE_ENDPOINT_ALLOW_LIST entry\"\n            ) from exc\n        if parsed.query or \";\" in parsed.path:\n            raise OutboundPolicyError(\n                \"PRIVATE_ENDPOINT_ALLOW_LIST entries must not include params or a query\"\n            )\n        endpoints.append(_endpoint(parsed))\n    return tuple(endpoints)\n\n\ndef _endpoint(parsed: SplitResult) -> Endpoint:\n    scheme, hostname, port = _origin(parsed.geturl())\n    return scheme, hostname, port, parsed.path or \"/\"\n\n\ndef _normalize_hostname(hostname: str) -> str:\n    value = hostname.strip().lower().rstrip(\".\")\n    if _parse_ip(value) is not None:","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/plugin/link/infra/tool_exector/ssrf_guard.py#L241-L277","documentation":"OutboundPolicyError raised while parsing the PRIVATE_ENDPOINT_ALLOW_LIST environment variable during SSRF guard initialization. Each comma-separated entry must parse as an absolute HTTP(S) URL via _parse_http_url; malformed entries are rejected so the private-endpoint allow list cannot silently contain unusable or dangerous values.","triggerScenarios":"from_environment() -> _parse_private_endpoints() encounters an entry in PRIVATE_ENDPOINT_ALLOW_LIST that _parse_http_url cannot parse — e.g. a value with no scheme ('myhost.internal'), a bare IP without scheme, or garbage characters/typo.","commonSituations":"Operators set PRIVATE_ENDPOINT_ALLOW_LIST in deployment env/docker-compose/helm values with hostnames instead of full URLs, leave stray commas producing empty-plus-garbage entries, or copy values with typos or shell-mangled characters.","solutions":["Rewrite each PRIVATE_ENDPOINT_ALLOW_LIST entry as a full URL including scheme, e.g. 'https://vault.internal:8200' instead of 'vault.internal:8200'.","Remove empty or junk entries (double commas, whitespace-only items) from the variable.","Print/echo the raw env var in the deployment environment to spot truncation or quoting mangling (e.g. unescaped special chars in docker-compose YAML).","Restart the service after fixing so from_environment() re-parses at startup."],"exampleFix":"// before\nPRIVATE_ENDPOINT_ALLOW_LIST=vault.internal:8200, db.corp\n// after\nPRIVATE_ENDPOINT_ALLOW_LIST=https://vault.internal:8200, https://db.corp:5432","handlingStrategy":"validation","validationCode":"import re\nURL_RE = re.compile(r\"^https?://[^/?#]+$\")\ndef validate_allow_list(raw: str) -> list[str]:\n    entries = [e.strip() for e in raw.split(\",\") if e.strip()]\n    bad = [e for e in entries if not URL_RE.match(e)]\n    if bad:\n        raise ValueError(f\"entries must be absolute URLs without query: {bad}\")\n    return entries","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include scheme and host in each entry","Never include '?' or ';' in allow-list entries","Add a startup smoke test that parses the env var","Document the expected format next to the env var in helm/compose files"],"tags":["ssrf","configuration","env-var","url-parsing"],"backgroundTag":"invalid-config-value","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}