larksuite/cli · error

%s contains dangerous Unicode characters

Error message

%s contains dangerous Unicode characters

What it means

RejectControlChars also rejects Unicode code points known to enable visual spoofing: bidirectional overrides, zero-width characters, and line/paragraph separators. A string containing these looks different from what it actually is (e.g. reversed filename extensions), so the library treats them as invalid input.

Source

Thrown at internal/charcheck/charcheck.go:21

// Package charcheck provides character-level security checks shared across
// path validation (localfileio) and input validation (validate) packages.
// Keeping these checks in one place ensures consistent detection of dangerous
// Unicode and control characters throughout the codebase.
package charcheck

import "fmt"

// RejectControlChars rejects C0 control characters (except \t and \n) and
// dangerous Unicode characters (Bidi overrides, zero-width, line/paragraph
// separators) that enable visual spoofing attacks.
func RejectControlChars(value, flagName string) error {
	for _, r := range value {
		if r != '\t' && r != '\n' && (r < 0x20 || r == 0x7f) {
			return fmt.Errorf("%s contains invalid control characters", flagName)
		}
		if IsDangerousUnicode(r) {
			return fmt.Errorf("%s contains dangerous Unicode characters", flagName)
		}
	}
	return nil
}

// IsDangerousUnicode identifies Unicode code points used for visual spoofing
// attacks. These characters are invisible or alter text direction, allowing
// attackers to make "report.exe" display as "report.txt" (Bidi override) or
// insert hidden content (zero-width characters).
func IsDangerousUnicode(r rune) bool {
	switch {
	case r >= 0x200B && r <= 0x200D: // zero-width space/non-joiner/joiner
		return true
	case r == 0xFEFF: // BOM / ZWNBSP
		return true
	case r >= 0x202A && r <= 0x202E: // Bidi: LRE/RLE/PDF/LRO/RLO
		return true
	case r >= 0x2028 && r <= 0x2029: // line/paragraph separator

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Remove the dangerous Unicode characters from the value
  2. Retype the value manually in plain ASCII or clean Unicode
  3. Normalize with a Unicode normalizer and strip bidi/zero-width code points before passing

Example fix

// before
name := "report\u202Etxt.exe" // RLO reversal
// after
name := "report.txt"
Defensive patterns

Strategy: validation

Validate before calling

func hasDangerousUnicode(s string) bool {
    for _, r := range s {
        if IsDangerousUnicode(r) { return true }
    }
    return false
}
if hasDangerousUnicode(fileName) { fileName = sanitizeUnicode(fileName) }

Type guard

func isUnicodeSafe(s string) bool {
    for _, r := range s {
        if IsDangerousUnicode(r) { return false }
    }
    return true
}

Prevention

When it happens

Trigger: A flag value containing U+202E (RLO), U+200B (zero-width space), U+2028/U+2029, or similar detected by IsDangerousUnicode, on any RejectControlChars-guarded input.

Common situations: Usernames or filenames crafted (or copy-pasted) with invisible/bidi characters; multilingual text with zero-width joiners from social platforms; homograph-spoofed file names.

Related errors


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