larksuite/cli · error

%s must not contain '..' path traversal

Error message

%s must not contain '..' path traversal

What it means

ResourceName splits the resource identifier on '/' and rejects any segment equal to '..', because path traversal could change which API endpoint the request targets (e.g. '../admin'). It is a defense-in-depth check alongside EncodePathSegment. The flag name is included so users know which input to fix.

Source

Thrown at internal/validate/resource.go:33

// unsafeResourceChars matches URL-special characters, control characters,
// and percent signs (to prevent %2e%2e encoding bypass).
var unsafeResourceChars = regexp.MustCompile(`[?#%\x00-\x1f\x7f]`)

// ResourceName validates an API resource identifier (messageId, fileToken, etc.)
// before it is interpolated into a URL path via fmt.Sprintf. It rejects path
// traversal (..), URL metacharacters (?#%), percent-encoded bypasses (%2e%2e),
// control characters, and dangerous Unicode.
//
// Without this check, an input like "../admin" or "?evil=true" in a message ID
// would alter the API endpoint the request is sent to. Works alongside
// EncodePathSegment for defense-in-depth.
func ResourceName(name, flagName string) error {
	if name == "" {
		return fmt.Errorf("%s must not be empty", flagName)
	}
	for _, seg := range strings.Split(name, "/") {
		if seg == ".." {
			return fmt.Errorf("%s must not contain '..' path traversal", flagName)
		}
	}
	if unsafeResourceChars.MatchString(name) {
		return fmt.Errorf("%s contains invalid characters", flagName)
	}
	for _, r := range name {
		if charcheck.IsDangerousUnicode(r) {
			return fmt.Errorf("%s contains dangerous Unicode characters", flagName)
		}
	}
	return nil
}

// EncodePathSegment percent-encodes user input for safe use as a single URL path
// segment (e.g. / → %2F, ? → %3F, # → %23), ensuring the value cannot alter the
// URL routing structure when interpolated into an API path.
//
// This provides defense-in-depth alongside ResourceName: ResourceName rejects known

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Use the actual opaque resource ID (e.g. om_xxx, app id) — not a path.
  2. Sanitize or reject path-like input before passing it; never build IDs from filesystem paths.
  3. If the ID was copied from a URL, extract only the final identifier segment.
  4. Use EncodePathSegment to percent-encode legitimate input containing slashes if the API expects encoded segments.

Example fix

// before
id="$tenant/$msgID"
lark-cli im message get --message-id "$id"
// after
lark-cli im message get --message-id "$msgID"  # pass the bare om_xxx ID only
Defensive patterns

Strategy: validation

Validate before calling

for _, seg := range strings.Split(id, "/") {
    if seg == ".." {
        return fmt.Errorf("id must not contain path traversal")
    }
}

Try / catch

if err := validate.ResourceName(id, "--message-id"); err != nil {
    return fmt.Errorf("rejecting unsuitable id: %w", err)
}

Prevention

When it happens

Trigger: validate.ResourceName receives a name containing a '/'-separated '..' segment — e.g. --message-id '../../admin' or an app ID built from untrusted path-like input.

Common situations: Passing filesystem-style relative paths where an API resource ID is expected, constructing IDs by concatenating user-controlled parts, or malicious input attempting endpoint manipulation.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/bddf663992bb0a2b. Report an issue: GitHub.