iflytek/astron-agent · error · OutboundPolicyError

Invalid DOMAIN_BLACK_LIST entry

Error message

Invalid DOMAIN_BLACK_LIST entry

What it means

When parsing DOMAIN_BLACK_LIST from the environment, each entry must be a bare hostname after wildcard/leading-dot stripping. An entry containing '://' or '/' is rejected because it looks like a URL or path rather than a hostname — the blacklist matches hosts, not full URLs.

Solutions

  1. Use bare hostnames only: evil.com instead of https://evil.com.
  2. Strip scheme and path: urllib.parse.urlsplit(entry).hostname to extract just the host.
  3. If path-based blocking is needed, it is not supported by this setting — handle at a different layer.
  4. Fix the env var so every comma-separated token is a hostname (wildcards like *.evil.com are allowed).

Example fix

// before
DOMAIN_BLACK_LIST=https://evil.com,evil.com/admin
// after
DOMAIN_BLACK_LIST=evil.com
Defensive patterns

Strategy: validation

Validate before calling

def valid_domain_entries(raw: str) -> bool:
    for entry in raw.split(","):
        v = entry.strip().lower().rstrip(".").lstrip("*.").lstrip(".")
        if v and ("://" in v or "/" in v):
            return False
    return True

Try / catch

try:
    policy = OutboundPolicy.from_environment()
except OutboundPolicyError as e:
    raise ConfigError(f"bad DOMAIN_BLACK_LIST: {e}") from e

Prevention

When it happens

Trigger: from_environment → _parse_domains encounters an entry like https://evil.com, evil.com/api, or http://10.0.0.1 after stripping '*.': '://' or '/' remains, raising immediately.

Common situations: Pasting a full URL into a domain blacklist env var; including a path pattern like evil.com/admin; mixing URL and host formats in one comma-separated list.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/f4f7a4d0aab8901f. Report an issue: GitHub.

Appendix: source

Thrown at core/plugin/link/infra/tool_exector/ssrf_guard.py:239

        try:
            networks.append(ipaddress.ip_network(value, strict=False))
        except ValueError as exc:
            raise OutboundPolicyError(f"Invalid {setting_name} entry") from exc
    return tuple(networks)


def _parse_domains(raw_value: str) -> Tuple[str, ...]:
    domains = []
    for entry in raw_value.split(","):
        value = entry.strip().lower().rstrip(".")
        if value.startswith("*."):
            value = value[2:]
        if value.startswith("."):
            value = value[1:]
        if not value:
            continue
        if "://" in value or "/" in value:
            raise OutboundPolicyError("Invalid DOMAIN_BLACK_LIST entry")
        try:
            # Use the same IDNA normalization as aiohttp/yarl applies to request hosts.
            # Python's built-in ``idna`` codec follows IDNA2003 and would otherwise
            # collapse distinct hosts such as faß.de and fass.de.
            domains.append(_normalize_hostname(value))
        except OutboundPolicyError as exc:
            raise OutboundPolicyError("Invalid DOMAIN_BLACK_LIST entry") from exc
    return tuple(domains)


def _parse_private_endpoints(raw_value: str) -> Tuple[Endpoint, ...]:
    endpoints = []
    for entry in raw_value.split(","):
        value = entry.strip()
        if not value:
            continue
        try:
            parsed = _parse_http_url(value)

View on GitHub (pinned to 5e758547a8)