JuliusBrussee/caveman · error

compat route path rejected

Error message

compat route path rejected: %w

What it means

validateCompatPath applies strict component validation to any path under /compat/ and wraps the underlying cause with 'compat route path rejected'. It exists so a path cannot change route identity after decoding by another proxy hop. The wrapped cause is one of: backslash, repeated separators, dot segments, or ambiguous escapes.

Solutions

  1. Remove backslashes, empty inner segments, and dot segments from the request path
  2. URL-encode payloads so no %2f, %5c, or %2e appear in the path (put variable data in the body or query where allowed)
  3. Fix the upstream BaseURL in config if it contains such components
  4. Send the request without a rawPath escape spelling that differs from the decoded path

Example fix

// before
GET /compat/openai/v1/chat/../completions

// after
GET /compat/openai/v1/chat/completions
Defensive patterns

Strategy: validation

Validate before calling

func safeCompatPath(p string) error {
    if strings.Contains(p, "\\") || strings.Contains(p, "..") || strings.Contains(p, "//") {
        return fmt.Errorf("unsafe path %q", p)
    }
    return nil
}

Try / catch

if err := ValidateRequestPath(req.URL); err != nil {
    log.Warnf("rejected compat path: %v", err)
    http.Error(w, "invalid path", http.StatusBadRequest)
    return
}

Prevention

When it happens

Trigger: Requesting any /compat/... path containing a backslash, '//' inside the path, '.'/'..' segments, or %2f/%5c/%2e escapes in Path or RawPath; configuring an upstream BaseURL whose path contains such components (via parseBaseURL's validation).

Common situations: Clients URL-encoding slashes in model names or resource ids; buggy client code double-encoding paths; misconfigured base URLs containing '..' or '//'; security scanners probing path traversal.

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


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/eb6e52636bab8dad. Report an issue: GitHub.

Appendix: source

Thrown at proxy/providers/openaicompat/openaicompat.go:482

// Gateways call this with the original URL (including RawPath), while the
// adapter MatchRoute/ResolveUpstreamURL checks provide a second fail-closed
// boundary for direct callers.
func ValidateRequestPath(u *url.URL) error {
	if u == nil {
		return fmt.Errorf("request URL is missing")
	}
	if !strings.HasPrefix(u.Path, "/compat/") {
		return nil
	}
	return validateCompatPath(u.Path, u.RawPath)
}

func validateCompatPath(path, rawPath string) error {
	if !strings.HasPrefix(path, "/compat/") {
		return nil
	}
	if err := validatePathComponents(path, rawPath); err != nil {
		return fmt.Errorf("compat route path rejected: %w", err)
	}
	return nil
}

func validatePathComponents(path, rawPath string) error {
	if strings.Contains(path, `\`) {
		return fmt.Errorf("backslash is not allowed in path")
	}
	segments := strings.Split(path, "/")
	for i, segment := range segments {
		if segment == "" && i > 0 && i < len(segments)-1 {
			return fmt.Errorf("repeated path separators are not allowed")
		}
		if segment == "." || segment == ".." {
			return fmt.Errorf("dot segments are not allowed in path")
		}
	}
	// URL.Path is decoded by net/url while RawPath retains a valid escaped

View on GitHub (pinned to 3ee70a1026)