googleapis/mcp-toolbox · error

path %q contains '..'

Error message

path %q contains '..'

What it means

ValidateLocalPath found a standalone ".." segment in the raw path — a path-traversal attempt (or mistake) that filepath.Clean would silently collapse, so it is rejected outright to keep the download/upload destination from escaping the intended location.

Source

Thrown at internal/tools/cloudstorage/cloudstoragecommon/paths.go:47

// remain the real isolation boundary; this check just prevents obvious
// traversal mistakes and forces callers to be explicit about where they want
// bytes to land. Confining a path to a configured directory is a separate
// concern; see ResolveWithinDir and ResolveSymlinks.
func ValidateLocalPath(p string) (string, error) {
	if p == "" {
		return "", fmt.Errorf("path is empty")
	}
	// Reject any ".." segment in the raw input. We check the raw input
	// (not just the cleaned output) so that escapes like
	// "/legit/../../etc/passwd" — which filepath.Clean collapses to an
	// innocuous-looking absolute path — are still rejected. Legitimate
	// names that happen to *contain* two dots (e.g. "foo..bar") are fine;
	// only a standalone ".." segment is disallowed.
	for _, seg := range strings.FieldsFunc(p, func(r rune) bool {
		return r == '/' || r == '\\'
	}) {
		if seg == ".." {
			return "", fmt.Errorf("path %q contains '..'", p)
		}
	}
	clean := filepath.Clean(p)
	if !filepath.IsAbs(clean) {
		return "", fmt.Errorf("path %q must be absolute", p)
	}
	return clean, nil
}

// ResolveSymlinks returns the final filesystem target of path, following every
// symbolic link along the way. Comparing *this* against a configured boundary —
// rather than the caller-supplied name — is what stops a path that merely looks
// like it sits inside the boundary from opening a file outside it.
//
// Paths whose trailing components do not exist yet (the normal case for a
// download destination) are resolved as deeply as the filesystem allows, and
// the missing components are appended literally.
//

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Remove ".." segments and use explicit absolute paths
  2. Construct paths from trusted, validated components
  3. Reject user-supplied relative path fragments at the tool boundary
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at internal/tools/cloudstorage/cloudstoragecommon/paths.go:47 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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