thanos-io/thanos · warning
invalid tenant ID
Error message
invalid tenant ID
What it means
errInvalidTenantID is returned by tenant resolvers (TenantID, TestSingleResolver) when the extracted tenant ID is unsafe — it contains path separators or unsafe path segments (e.g. "..", "/", "\\"). It guards multi-tenancy against path traversal via the X-Scope-OrgID header.
Solutions
- Use a tenant ID restricted to safe characters (letters, digits, dash, underscore)
- Sanitize or reject such header values at the ingress/proxy before they reach Cortex
- If legitimate tenants need hierarchical names, choose a different separator convention
Example fix
// before curl -H 'X-Scope-OrgID: ../admin' ... // after curl -H 'X-Scope-OrgID: tenant-admin' ...
Defensive patterns
Strategy: validation
Validate before calling
var tenantIDRe = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`)
func validTenantID(id string) bool { return tenantIDRe.MatchString(id) } Type guard
func safeTenant(id string) bool {
return !strings.ContainsAny(id, "\\/") && !strings.Contains(id, "..")
} Try / catch
tid, err := resolver.TenantID(ctx)
if errors.Is(err, tenant.ErrInvalidTenantID) {
http.Error(w, "invalid tenant ID", http.StatusBadRequest)
return
} Prevention
- Restrict tenant header values to [a-zA-Z0-9_-] at ingress
- Reject requests with suspicious tenant headers at the proxy (rate-limit + 400)
- Never build tenant IDs from user-controlled path components
When it happens
Trigger: Sending X-Scope-OrgID (or the configured tenant header) with values containing "/", "\\", or path segments like ".." so containsUnsafePathSegments returns true in resolver.go:84.
Common situations: Proxies/clients injecting odd tenant headers; malicious probing for path traversal in store paths; misconfigured load balancers that mangle header values; test suites expecting IDs with slashes.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- query-frontend.org-id-header and…
- use of multiple cache storage systems is not supported
- invalid duration
- unsupported compression type
- frontend.cache-queryable-samples-stats may only be enabled…
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/47d44045212c80c4.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cortex/tenant/resolver.go:74
return &SingleResolver{}
}
type SingleResolver struct {
}
// containsUnsafePathSegments will return true if the string is a directory
// reference like `.` and `..` or if any path separator character like `/` and
// `\` can be found.
func containsUnsafePathSegments(id string) bool {
// handle the relative reference to current and parent path.
if id == "." || id == ".." {
return true
}
return strings.ContainsAny(id, "\\/")
}
var errInvalidTenantID = errors.New("invalid tenant ID")
func (t *SingleResolver) TenantID(ctx context.Context) (string, error) {
//lint:ignore faillint wrapper around upstream method
id, err := user.ExtractOrgID(ctx)
if err != nil {
return "", err
}
if containsUnsafePathSegments(id) {
return "", errInvalidTenantID
}
return id, nil
}
func (t *SingleResolver) TenantIDs(ctx context.Context) ([]string, error) {
orgID, err := t.TenantID(ctx)
if err != nil {View on GitHub (pinned to 35b8b99117)