{"record":{"id":"07496e2582f7b9c8","repo":"neondatabase/neon","slug":"invalid-address-format-remote-endpoint-expected","errorCode":null,"errorMessage":"Invalid address format {remote_endpoint}, expected host:port","messagePattern":"Invalid address format (.+?), expected host:port","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compute_tools/src/rsyslog.rs","lineNumber":113,"sourceCode":"    } else {\n        tls = \"false\".to_string();\n        remote_plain_endpoint\n    };\n    // Urlify the remote_endpoint, so parsing can be done with url::Url.\n    let url_str = format!(\"http://{remote_endpoint}\");\n    let url = Url::parse(&url_str).map_err(|err| {\n        anyhow!(\"Error parsing {remote_endpoint}, expected host:port, got {err:?}\")\n    })?;\n\n    let is_valid = url.scheme() == \"http\"\n        && url.path() == \"/\"\n        && url.query().is_none()\n        && url.fragment().is_none()\n        && url.username() == \"\"\n        && url.password().is_none();\n\n    if !is_valid {\n        return Err(anyhow!(\n            \"Invalid address format {remote_endpoint}, expected host:port\"\n        ));\n    }\n    let host = match url.host() {\n        Some(Host::Domain(h)) if hostname_validator::is_valid(h) => h.to_string(),\n        Some(Host::Ipv4(ip4)) => ip4.to_string(),\n        Some(Host::Ipv6(ip6)) => ip6.to_string(),\n        _ => return Err(anyhow!(\"Invalid host\")),\n    };\n    let port = url\n        .port()\n        .ok_or_else(|| anyhow!(\"Invalid port in {remote_endpoint}\"))?;\n\n    Ok((host, port, tls))\n}\n\nfn generate_audit_rsyslog_config(\n    log_directory: String,","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/compute_tools/src/rsyslog.rs#L95-L131","documentation":"The synthetic http:// URL parsed, but contained components a bare host:port must not have: a path, query, fragment, username or password. The code checks url.scheme() == \"http\" && path == \"/\" && query/fragment/username/password are all empty and rejects anything else. Note the check runs after successful parsing, so this is a semantic-format rejection, not a URL syntax error.","triggerScenarios":"Endpoint values like 'collector.host:514/path', 'user@collector.host:514', 'user:pass@collector.host:514', or 'collector.host:514?q=1' pass Url::parse but embed forbidden components.","commonSituations":"Paste-in values copied from full http:// collector URLs; endpoints documented with auth userinfo; trailing slashes added by convention.","solutions":["Strip scheme, path, query, fragment and userinfo - supply only host:port","If the value came from a full URL, extract just the authority before configuring audit logging","Add a startup assertion rejecting '/', '?', '#', '@', '://' in endpoint values"],"exampleFix":"// before\nparse_audit_syslog_address(\"collector.host.tld:514/path?x=1\", \"\");\n\n// after\nparse_audit_syslog_address(\"collector.host.tld:514\", \"\");","handlingStrategy":"validation","validationCode":"// strip URL decorations down to a bare host:port authority\nlet endpoint = full_url\n    .trim_start_matches(\"http://\")\n    .trim_start_matches(\"https://\")\n    .split('/').next().unwrap_or(\"\")\n    .split('?').next().unwrap_or(\"\")\n    .split('#').next().unwrap_or(\"\");\nassert!(endpoint.split(':').count() <= 2 || endpoint.starts_with('['), \"expected host:port\");","typeGuard":"fn is_bare_host_port(endpoint: &str) -> bool {\n    !endpoint.contains('/') && !endpoint.contains('?') && !endpoint.contains('#')\n        && !endpoint.contains('@') && !endpoint.contains(\"://\")\n        && endpoint.rsplit_once(':').is_some()\n}","tryCatchPattern":"let is_valid = url.scheme() == \"http\" && url.path() == \"/\" && url.query().is_none()\n    && url.fragment().is_none() && url.username().is_empty() && url.password().is_none();\nif !is_valid {\n    return Err(anyhow!(\"Invalid address format {remote_endpoint}, expected host:port\"));\n}","preventionTips":["Store endpoints as bare host:port, never full URLs","Reject '/', '?', '#', '@', '://' in endpoint values at ingestion","Document the expected format next to the env var definition"],"tags":["url-parsing","host-port","validation","rsyslog","rust"],"backgroundTag":"invalid-host-port-format","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}