{"record":{"id":"ed92af23bff84c84","repo":"tinyhumansai/openhuman","slug":"url-port-must-be-numeric","errorCode":null,"errorMessage":"URL port must be numeric","messagePattern":"URL port must be numeric","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/openhuman/tools/impl/network/url_guard.rs","lineNumber":276,"sourceCode":"fn extract_port(url: &str) -> anyhow::Result<u16> {\n    let is_http = url.starts_with(\"http://\");\n    let rest = url\n        .strip_prefix(\"http://\")\n        .or_else(|| url.strip_prefix(\"https://\"))\n        .ok_or_else(|| anyhow::anyhow!(\"Only http:// and https:// URLs are allowed\"))?;\n\n    let authority = rest\n        .split(['/', '?', '#'])\n        .next()\n        .ok_or_else(|| anyhow::anyhow!(\"Invalid URL\"))?;\n\n    if authority.starts_with('[') {\n        anyhow::bail!(\"IPv6 hosts are not supported in http_request\");\n    }\n\n    if let Some((_, port)) = authority.rsplit_once(':') {\n        if port.is_empty() || !port.chars().all(|ch| ch.is_ascii_digit()) {\n            anyhow::bail!(\"URL port must be numeric\");\n        }\n        return port\n            .parse::<u16>()\n            .map_err(|_| anyhow::anyhow!(\"URL port is out of range\"));\n    }\n\n    Ok(if is_http { 80 } else { 443 })\n}\n\npub(super) fn host_matches_allowlist(host: &str, allowed_domains: &[String]) -> bool {\n    allowed_domains.iter().any(|domain| {\n        // `\"*\"` is the explicit allow-all wildcard (the \"Allow all sites\"\n        // toggle), mirroring the browser tool. Local/private hosts are still\n        // rejected upstream by `is_private_or_local_host`, so a wildcard only\n        // opens *public* hosts, never the loopback/RFC1918 SSRF surface.\n        domain == \"*\"\n            || host == domain\n            || host","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/tools/impl/network/url_guard.rs#L258-L294","documentation":"extract_port split the authority on the last ':' and the right-hand side is not a parseable number, so no port can be derived for the request; this catches malformed authorities like 'host:abc'.","triggerScenarios":"Thrown at src/openhuman/tools/impl/network/url_guard.rs:276 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Omit the port to use the scheme default (80/443)","Write the port in decimal form, e.g. 'https://host:8443/path'"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}