googleapis/mcp-toolbox · error

path cannot contain dot segments (..)

Error message

path cannot contain dot segments (..)

What it means

After parsing the relative path, getURL rejects any path segment equal to '..' before resolving against the BaseURL. Dot segments could make the resolved URL climb out of the configured base path scope, so they are refused outright as a path-traversal defense.

Source

Thrown at internal/tools/http/http.go:209

		return "", fmt.Errorf("error parsing base URL: %s", err)
	}
	if baseParsedURL.Scheme == "" || baseParsedURL.Host == "" {
		return "", fmt.Errorf("base URL must include scheme and host")
	}

	relativePath := templatedPath.String()
	relParsedURL, err := url.Parse(relativePath)
	if err != nil {
		return "", fmt.Errorf("error parsing URL path: %s", err)
	}
	if relParsedURL.Scheme != "" || relParsedURL.Host != "" || relParsedURL.User != nil {
		return "", fmt.Errorf("path must be relative and cannot override base host")
	}

	// Reject dot segments before resolution
	for _, segment := range strings.Split(relParsedURL.Path, "/") {
		if segment == ".." {
			return "", fmt.Errorf("path cannot contain dot segments (..)")
		}
	}

	// Create URL based on BaseURL and Path
	// Attach query parameters
	parsedURL := baseParsedURL.ResolveReference(relParsedURL)

	// Verify final path stays within base path scope
	basePath := baseParsedURL.Path
	finalPath := parsedURL.Path
	if basePath != "/" {
		requiredPrefix := strings.TrimSuffix(basePath, "/") + "/"
		if finalPath != basePath && !strings.HasPrefix(finalPath, requiredPrefix) {
			return "", fmt.Errorf("resolved path %q escapes base path %q", finalPath, basePath)
		}
	}

	// Get existing query parameters from the URL

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Remove '..' segments from the path and specify the full intended path from the base (e.g. use '/admin' instead of '/v1/../admin')
  2. Normalize/resolve the desired path client-side before passing it, so only a clean absolute-relative path reaches the tool
  3. If traversal out of the base path is genuinely required, configure the tool's BaseURL at the higher-level path

Example fix

// before
path: /v1/../admin/settings
// after
path: /admin/settings
Defensive patterns

Strategy: validation

Validate before calling

for _, seg := range strings.Split(pathParam, "/") {
    if seg == ".." {
        return fmt.Errorf("dot segments not allowed in path: %q", pathParam)
    }
}

Type guard

func hasDotSegments(p string) bool {
    for _, seg := range strings.Split(p, "/") {
        if seg == ".." { return true }
    }
    return false
}

Prevention

When it happens

Trigger: getURL is called with a path containing a literal '..' segment such as '/v1/../admin' or '/files/../../etc' — typically produced by user/model-supplied path parameters or naive path joins.

Common situations: LLM-generated tool arguments containing '..'; clients attempting to escape a restricted API prefix; accidental double-resolution where a caller pre-joins paths with '..' to 'go up' a level.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/d6e512840a330bc0. Report an issue: GitHub.