{"record":{"id":"b5a0675ac27432ae","repo":"zeroclaw-labs/zeroclaw","slug":"only-http-and-https-urls-are-allowed-b5a067","errorCode":null,"errorMessage":"Only http:// and https:// URLs are allowed","messagePattern":"Only http:// and https:// URLs are allowed","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/http_request.rs","lineNumber":131,"sourceCode":"\n    #[cfg(test)]\n    fn validate_url(&self, raw_url: &str) -> anyhow::Result<String> {\n        Ok(self.validate_url_policy(raw_url)?.url)\n    }\n\n    fn validate_url_policy(&self, raw_url: &str) -> anyhow::Result<HttpRequestUrlPolicy> {\n        let url = raw_url.trim();\n\n        if url.is_empty() {\n            anyhow::bail!(\"URL cannot be empty\");\n        }\n\n        if url.chars().any(char::is_whitespace) {\n            anyhow::bail!(\"URL cannot contain whitespace\");\n        }\n\n        if !url.starts_with(\"http://\") && !url.starts_with(\"https://\") {\n            anyhow::bail!(\"Only http:// and https:// URLs are allowed\");\n        }\n\n        if self.allowed_domains.is_empty() {\n            anyhow::bail!(\n                \"HTTP request tool is enabled but no allowed_domains are configured. Add [http_request].allowed_domains in config.toml\"\n            );\n        }\n\n        let host = extract_host(url)?;\n        if let Ok(ip) = host.parse::<IpAddr>() {\n            if domain_guard::is_known_cloud_metadata_endpoint(ip) {\n                anyhow::bail!(\"Blocked cloud metadata host: {host}\");\n            }\n            if domain_guard::is_cloud_metadata_ip(ip) {\n                anyhow::bail!(\n                    \"Blocked link-local host: {host}; 169.254.0.0/16 is blocked unconditionally \\\n                     because cloud metadata services are hosted in that range\"\n                );","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/http_request.rs#L113-L149","documentation":"Thrown by HttpRequestTool::validate_url_policy (crates/zeroclaw-tools/src/http_request.rs:131) when the trimmed URL does not literally start with \"http://\" or \"https://\". The tool is an allowlisted egress tool and deliberately refuses every other scheme (ftp, file, gopher, data, ws, ...). Note the check is case-sensitive on the prefix, so \"HTTP://example.com\" is also rejected here.","triggerScenarios":"Passing a bare host such as \"example.com/path\" with no scheme; passing ftp://, file:///etc/passwd, or data: URLs; passing \"HTTP://\" or \"HTTPS://\" with uppercase scheme letters (case-sensitive starts_with); passing a URL with leading whitespace already trimmed but scheme misspelled as \"http:/\" (single slash).","commonSituations":"Users or models pasting a domain without a scheme; SSRF-probing attempts with file:// or gopher://; template engines that uppercase the scheme; typos when hand-assembling URLs.","solutions":["Prefix the target with http:// or https:// (lowercase), e.g. \"https://example.com/path\".","Normalize the scheme to lowercase before calling the tool if the URL comes from user input.","For file access use the dedicated file tools, not http_request; for other protocols use a purpose-built client outside this tool."],"exampleFix":"// before\nlet args = json!({\"url\": \"example.com/api/v1\"}); // or \"HTTP://example.com\"\n\n// after\nlet args = json!({\"url\": \"https://example.com/api/v1\"});","handlingStrategy":"validation","validationCode":"fn scheme_allowed(url: &str) -> bool {\n    let u = url.trim().to_ascii_lowercase();\n    u.starts_with(\"http://\") || u.starts_with(\"https://\")\n}","typeGuard":"fn is_http_url(url: &str) -> bool {\n    let u = url.trim().to_ascii_lowercase();\n    u.starts_with(\"http://\") || u.starts_with(\"https://\")\n}","tryCatchPattern":"let result = tool.execute(args).await?;\nif let Some(err) = &result.error {\n    if err.contains(\"Only http:// and https:// URLs are allowed\") {\n        // normalize scheme to lowercase https:// and re-submit\n    }\n}","preventionTips":["Default to https:// when a bare host is supplied by a user or model.","Lowercase the scheme before calling the tool (the check is case-sensitive).","Treat file://, ftp://, gopher:// attempts as injection signals and log them."],"tags":["http","url","scheme","ssrf","validation","zeroclaw"],"backgroundTag":"url-scheme-not-allowed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}