filepath.clean仅标准化路径,不防越界,必须先clean再用strings.hasprefix校验白名单前缀(须以/结尾),且需前置url解码、过滤空字节,最后用os.o_nofollow打开。

用 filepath.Clean 和 strings.HasPrefix 做路径白名单校验
直接拼接用户输入的路径再调用 os.Open 是高危操作,filepath.Clean 不是安全函数,它只标准化、不拦截。比如 filepath.Clean("/var/www/../etc/passwd") 返回 /var/etc/passwd,依然越界。
正确做法是:先 filepath.Clean,再检查是否以白名单根目录开头:
- 必须在
filepath.Clean后立刻做strings.HasPrefix(cleaned, allowedRoot),且allowedRoot本身要以/结尾(如"./data/"),否则"./data2"也会被误判通过 - Windows 下注意盘符,
allowedRoot应为"C:\data\"或统一转成filepath.ToSlash后比对 - 若
cleaned长度小于allowedRoot长度,HasPrefix必然失败,这是正常防护逻辑,无需额外 panic
用 filepath.Rel 反向验证路径是否逃逸
filepath.Rel(allowedRoot, fullPath) 是比字符串前缀更可靠的越界检测方式:它尝试计算 fullPath 相对于 allowedRoot 的相对路径,一旦结果含 ".." 或报错,说明路径逃逸。
Go语言(Golang)1.26.0
下载
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 示例:
filepath.Rel("./uploads", "./uploads/../etc/shadow")返回"../etc/shadow"→ 拒绝 - 必须确保
allowedRoot和fullPath都已用filepath.Clean处理过,否则Rel行为不可靠 - 该方法无法防御空字节绕过,仍需前置过滤
