{"record":{"id":"4dc921d6ed93e907","repo":"crewAIInc/crewAI","slug":"url-scheme-must-be-http-or-https","errorCode":null,"errorMessage":"URL scheme must be 'http' or 'https'","messagePattern":"URL scheme must be 'http' or 'https'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"lib/crewai-tools/src/crewai_tools/aws/bedrock/browser/browser_toolkit.py","lineNumber":142,"sourceCode":"            return False\n\n\n# Tool classes\nclass NavigateTool(BrowserBaseTool):\n    \"\"\"Tool for navigating a browser to a URL.\"\"\"\n\n    name: str = \"navigate_browser\"\n    description: str = \"Navigate a browser to the specified URL\"\n    args_schema: type[BaseModel] = NavigateToolInput\n\n    def _run(self, url: str, thread_id: str = \"default\", **kwargs: Any) -> str:\n        \"\"\"Use the sync tool.\"\"\"\n        try:\n            page = self.get_sync_page(thread_id)\n\n            parsed_url = urlparse(url)\n            if parsed_url.scheme not in (\"http\", \"https\"):\n                raise ValueError(\"URL scheme must be 'http' or 'https'\")\n\n            # Navigate to URL\n            response = page.goto(url)\n            status = response.status if response else \"unknown\"\n            return f\"Navigating to {url} returned status code {status}\"\n        except Exception as e:\n            return f\"Error navigating to {url}: {e!s}\"\n\n    async def _arun(self, url: str, thread_id: str = \"default\", **kwargs: Any) -> str:\n        \"\"\"Use the async tool.\"\"\"\n        try:\n            page = await self.get_async_page(thread_id)\n\n            parsed_url = urlparse(url)\n            if parsed_url.scheme not in (\"http\", \"https\"):\n                raise ValueError(\"URL scheme must be 'http' or 'https'\")\n\n            # Navigate to URL","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/aws/bedrock/browser/browser_toolkit.py#L124-L160","documentation":"A ValueError raised by the sync NavigateBrowserTool._run when the target URL's scheme is neither http nor https (checked via urlparse). It is then caught by the method's own `except Exception` and returned as the string \"Error navigating to <url>: URL scheme must be 'http' or 'https'\" rather than propagated — so callers see an error string, not an exception.","triggerScenarios":"Calling the navigate_browser tool with URLs like 'ftp://example.com', 'file:///etc/passwd', 'chrome://settings', or with no scheme at all ('example.com' parses with scheme=''), or javascript: URLs from an LLM.","commonSituations":"An LLM agent passing a bare domain without https://; malicious or malformed URLs from user input reaching the browser tool; attempts to use file:// or internal chrome:// schemes which the toolkit deliberately blocks as a safety measure.","solutions":["Normalize URLs before invoking: prepend 'https://' when the scheme is missing.","Reject non-http(s) input upstream (validate user/LLM URL output) — the tool intentionally blocks file:, ftp:, javascript:.","If you need local files, serve them over a local http server instead of file://."],"exampleFix":"# before\nresult = navigate_tool._run(url=\"example.com\")\n\n# after\nfrom urllib.parse import urlparse\ndef ensure_scheme(url: str) -> str:\n    return url if urlparse(url).scheme in (\"http\", \"https\") else f\"https://{url}\"\nresult = navigate_tool._run(url=ensure_scheme(\"example.com\"))","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\ndef normalize_url(url: str) -> str | None:\n    url = url.strip()\n    if not url:\n        return None\n    if urlparse(url).scheme not in (\"http\", \"https\"):\n        url = \"https://\" + url.lstrip(\"/\")\n    return url if urlparse(url).scheme in (\"http\", \"https\") else None","typeGuard":"def is_navigable_url(url: str) -> bool:\n    return urlparse(url).scheme in (\"http\", \"https\")","tryCatchPattern":"# The tool returns error strings instead of raising — check the return value:\nresult = navigate_tool._run(url=url)\nif result.startswith(\"Error navigating\"):\n    url = f\"https://{url}\"  # or log/skip\n    result = navigate_tool._run(url=url)","preventionTips":["Normalize LLM-generated URLs (prepend https:// when scheme is missing) before tool calls.","Treat returned 'Error navigating to ...' strings as failures in orchestration logic.","Never feed raw user input or file:// URLs to the browser toolkit."],"tags":["aws","bedrock","browser","url","validation"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}