{"record":{"id":"8225012523708a6c","repo":"googleapis/mcp-toolbox","slug":"path-must-be-relative-and-cannot-override-base-hos","errorCode":null,"errorMessage":"path must be relative and cannot override base host","messagePattern":"path must be relative and cannot override base host","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/http/http.go","lineNumber":203,"sourceCode":"\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error replacing pathParams: %s\", err)\n\t}\n\n\tbaseParsedURL, err := url.Parse(baseURL)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error parsing base URL: %s\", err)\n\t}\n\tif baseParsedURL.Scheme == \"\" || baseParsedURL.Host == \"\" {\n\t\treturn \"\", fmt.Errorf(\"base URL must include scheme and host\")\n\t}\n\n\trelativePath := templatedPath.String()\n\trelParsedURL, err := url.Parse(relativePath)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error parsing URL path: %s\", err)\n\t}\n\tif relParsedURL.Scheme != \"\" || relParsedURL.Host != \"\" || relParsedURL.User != nil {\n\t\treturn \"\", fmt.Errorf(\"path must be relative and cannot override base host\")\n\t}\n\n\t// Reject dot segments before resolution\n\tfor _, segment := range strings.Split(relParsedURL.Path, \"/\") {\n\t\tif segment == \"..\" {\n\t\t\treturn \"\", fmt.Errorf(\"path cannot contain dot segments (..)\")\n\t\t}\n\t}\n\n\t// Create URL based on BaseURL and Path\n\t// Attach query parameters\n\tparsedURL := baseParsedURL.ResolveReference(relParsedURL)\n\n\t// Verify final path stays within base path scope\n\tbasePath := baseParsedURL.Path\n\tfinalPath := parsedURL.Path\n\tif basePath != \"/\" {\n\t\trequiredPrefix := strings.TrimSuffix(basePath, \"/\") + \"/\"","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/http/http.go#L185-L221","documentation":"The HTTP tool resolves a user-supplied (templated) path against a fixed BaseURL. This library throws this error when the path is not purely relative — i.e. it contains a scheme (http://), a host, or userinfo — because letting the path override the base host would allow requests to arbitrary servers, breaking the tool's configured destination and enabling SSRF.","triggerScenarios":"getURL is called (via Invoke) with a Path parameter that parses as an absolute URL, e.g. the caller passes 'https://evil.example.com/api' or '//evil.example.com/api' or 'user@host/path' as the templated path instead of a relative path like '/api/items'.","commonSituations":"Developers template the full URL into the path parameter because the model or client handed them a complete URL; config authors define an http tool whose base URL already includes a suffix path and then pass an absolute URL hoping to change hosts; SSRF-probe requests attempting host override.","solutions":["Pass only the relative path portion (e.g. '/v1/items?id=1') in the path parameter and keep the host in the tool's BaseURL configuration","If a different host is needed, define a separate http tool source with that BaseURL instead of overriding the path","Check the templated values being substituted into the path (custom functions/templates may inject a full URL); strip scheme+host before substitution"],"exampleFix":"// before\npath: https://api.example.com/v1/items\n// after\npath: /v1/items","handlingStrategy":"validation","validationCode":"u, err := url.Parse(pathParam)\nif err != nil || u.Scheme != \"\" || u.Host != \"\" || u.User != nil {\n    return fmt.Errorf(\"path must be relative: %q\", pathParam)\n}","typeGuard":"func isRelativePath(p string) bool {\n    u, err := url.Parse(p)\n    return err == nil && u.Scheme == \"\" && u.Host == \"\" && u.User == nil\n}","tryCatchPattern":null,"preventionTips":["Always keep the host in the tool's BaseURL config, never in the path parameter","Sanitize model/client-supplied URLs by extracting only the path portion before substitution","Add a pre-invocation check that url.Parse of the path yields empty Scheme and Host"],"tags":["http","url-validation","ssrf","security"],"backgroundTag":"absolute-url-in-relative-path","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}