Private
Public Access
1
0
Files
u-desk/internal/filesystem/path_validator.go
绝尘 eb5b85e007 新增:多文件预览Tab系统+脏标记+关闭确认+路径黑名单优化
- useMultiPreview composable管理多Tab状态、会话持久化
- 面包屑状态dot移除
- 放开Program Files目录访问限制
2026-05-05 00:10:39 +08:00

203 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package filesystem
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
)
// PathValidator 路径验证器接口
// 提供统一的路径安全检查,避免重复代码
type PathValidator interface {
// Validate 验证路径并返回详细的错误信息
Validate(path string) *ValidationError
// IsSafe 快速检查路径是否安全
IsSafe(path string) bool
// IsSensitive 检查路径是否为敏感路径
IsSensitive(path string) bool
}
// ValidationError 验证错误
type ValidationError struct {
Path string
Reason string
IsError bool // true=禁止访问, false=敏感路径
}
func (e *ValidationError) Error() string {
if e.IsError {
return fmt.Sprintf("路径验证失败: %s - %s", e.Path, e.Reason)
}
return fmt.Sprintf("敏感路径警告: %s - %s", e.Path, e.Reason)
}
// DefaultPathValidator 默认路径验证器实现
type DefaultPathValidator struct {
config *Config
}
// NewPathValidator 创建新的路径验证器
func NewPathValidator(config *Config) PathValidator {
return &DefaultPathValidator{
config: config,
}
}
// Validate 验证路径
func (v *DefaultPathValidator) Validate(path string) *ValidationError {
// 清理路径
cleanPath := filepath.Clean(path)
// 1. 检查路径遍历攻击
if strings.Contains(cleanPath, PathTraversalPattern) {
return &ValidationError{
Path: path,
Reason: "检测到路径遍历尝试",
IsError: true,
}
}
// 2. 检查符号链接
if !v.config.Security.PathValidation.AllowSymlinks {
if fi, err := os.Lstat(path); err == nil && fi.Mode()&os.ModeSymlink != 0 {
return &ValidationError{
Path: path,
Reason: "不允许访问符号链接",
IsError: true,
}
}
}
// 3. 检查UNC路径Windows
if runtime.GOOS == "windows" && !v.config.Security.PathValidation.AllowUNCPaths {
if strings.HasPrefix(cleanPath, `\\`) {
return &ValidationError{
Path: path,
Reason: "不允许访问UNC网络路径",
IsError: true,
}
}
}
// 4. Windows特定检查
if runtime.GOOS == "windows" && v.config.Security.PathValidation.CheckWindowsSystemPaths {
if err := v.checkWindowsSystemPaths(cleanPath); err != nil {
return err
}
}
// 5. 检查敏感路径
if v.isSensitivePath(cleanPath) {
return &ValidationError{
Path: path,
Reason: "访问敏感路径",
IsError: false, // 警告而非错误
}
}
return nil
}
// IsSafe 快速检查路径是否安全
func (v *DefaultPathValidator) IsSafe(path string) bool {
err := v.Validate(path)
return err == nil || !err.IsError
}
// IsSensitive 检查路径是否为敏感路径
func (v *DefaultPathValidator) IsSensitive(path string) bool {
cleanPath := filepath.Clean(path)
return v.isSensitivePath(cleanPath)
}
// checkWindowsSystemPaths 检查Windows系统路径
func (v *DefaultPathValidator) checkWindowsSystemPaths(path string) *ValidationError {
lowerPath := strings.ToLower(path)
// 检查盘符
if len(lowerPath) >= 3 && lowerPath[1] == ':' {
driveLetter := lowerPath[0:1]
// 检查系统核心目录
forbiddenDirs := []string{
driveLetter + ":\\windows",
driveLetter + ":\\system volume information",
driveLetter + ":\\boot",
}
for _, fb := range forbiddenDirs {
if strings.HasPrefix(lowerPath, fb) {
return &ValidationError{
Path: path,
Reason: "禁止访问系统关键目录",
IsError: true,
}
}
}
// 检查用户配置目录(可能包含敏感信息)
forbiddenPaths := []string{
"\\.ssh\\",
"\\.gnupg\\",
"\\.config\\",
"\\appdata\\roaming\\mozilla\\",
"\\appdata\\roaming\\google\\chrome\\",
"\\appdata\\local\\google\\user data\\",
}
for _, fp := range forbiddenPaths {
if strings.Contains(lowerPath, fp) {
return &ValidationError{
Path: path,
Reason: "禁止访问敏感配置目录",
IsError: true,
}
}
}
}
return nil
}
// isSensitivePath 检查是否为敏感路径
func (v *DefaultPathValidator) isSensitivePath(path string) bool {
lowerPath := strings.ToLower(filepath.Clean(path))
// 检查配置的敏感路径列表
for _, sp := range v.config.Security.PathValidation.SensitivePaths {
if strings.Contains(lowerPath, strings.ToLower(sp)) {
return true
}
}
return false
}
// 默认路径验证器(缓存,避免每次调用重复初始化)
var (
defaultValidatorOnce sync.Once
defaultValidator PathValidator
)
func getDefaultValidator() PathValidator {
defaultValidatorOnce.Do(func() {
defaultValidator = NewPathValidator(DefaultConfig())
})
return defaultValidator
}
// isSafePath 兼容函数:保持向后兼容
func isSafePath(path string) bool {
return getDefaultValidator().IsSafe(path)
}
// isSensitivePath 兼容函数:保持向后兼容
func isSensitivePath(path string) bool {
return getDefaultValidator().IsSensitive(path)
}