mirror of
https://github.com/larksuite/cli.git
synced 2026-07-06 00:06:28 +08:00
* feat: add FileIO extension for file transfer abstraction Introduce extension/fileio package with Provider/FileIO/File interfaces and a global registry, following the same pattern as extension/credential. - Add LocalFileIO default implementation with path validation and atomic writes - Wire FileIOProvider into Factory and resolve at runtime via RuntimeContext.FileIO() - Factory holds Provider (not resolved instance), deferring resolution to execution time
46 lines
1.6 KiB
Go
46 lines
1.6 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
// 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
|
|
return true
|
|
case r >= 0x2066 && r <= 0x2069: // Bidi isolates: LRI/RLI/FSI/PDI
|
|
return true
|
|
}
|
|
return false
|
|
}
|