必须用 os.lstat 判断符号链接,因 os.stat 会跟随链接返回目标文件信息,导致无法识别链接本身;正确做法是先 os.lstat 获取文件自身信息,再用 fi.mode().issymlink()(go≥1.19)或 fi.mode()&os.modesymlink!=0 判断。

必须用 os.Lstat,os.Stat 会跳转并返回目标信息,完全不可靠。
为什么 os.Stat 不能用来判断符号链接
os.Stat 默认跟随符号链接,它返回的是目标文件的 FileInfo,不是链接本身。比如 os.Stat("mylink") 返回的是 /etc/passwd 的元数据,你根本不知道自己正在操作一个软链接。
- 你以为在读普通文件,实际已穿透到任意路径
-
fi.Mode()&os.ModeSymlink != 0永远为 false,因为返回的Mode是目标的,不是链接的 - 权限、大小、类型全按目标算,逻辑彻底错位
正确判断:三步缺一不可
只调用一次 os.Lstat 并检查模式位,是最小可靠动作:
- 先调用
fi, err := os.Lstat(path)—— 必须用Lstat,它不解析链接,只读路径自身 inode - 检查错误:
os.IsNotExist(err)表示链接文件本身不存在;os.IsPermission(err)在 rootless 容器或只读挂载点上常见,需降级处理 - 再判断模式:
fi.Mode()&os.ModeSymlink != 0(Go fi.Mode().IsSymlink()(Go ≥ 1.19)
示例:
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
fi, err := os.Lstat("config.link")
if err != nil {
if os.IsNotExist(err) {
// 链接文件自己就不存在
}
return false, err
}
return fi.Mode()&os.ModeSymlink != 0, nil
常见误判场景与坑
坏链(dangling symlink)最容易被忽略:链接文件存在,但指向的目标路径不存在。此时 os.Lstat 成功返回,Mode 带 os.ModeSymlink,但 os.Stat 和 filepath.EvalSymlinks 全部失败。
- 不要只靠
os.Stat是否报错来反推是否为链接 —— 它对坏链也报错,但你已经错过了链接身份 - Windows 上
os.Lstat对坏链可能返回file does not exist,而不是明确的链接类型,需结合平台行为容错 - 别在没确认是链接前就调
filepath.EvalSymlinks—— 它不做安全校验,传入恶意路径直接解析出/etc/shadow
硬链接无法用 Mode 判断,别混淆
os.FileMode 没有硬链接标志位。硬链接和普通文件的 Mode 完全一致,唯一区分方式是查底层 st_nlink > 1 且非符号链接。这和符号链接是两类问题,混用判断逻辑必然出错。
真正要拦住符号链接攻击,核心就三点:os.Lstat 看身份、filepath.EvalSymlinks 看落点、strings.HasPrefix 看范围 —— 少一步,门就开着。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










