最可靠路径校验方法是路径归一化加白名单约束:先用 realpath -m 归一化路径,再检查是否在以 / 开头的严格白名单前缀内,并辅以非法字符预筛、空值校验及存在性/权限验证。

核心原则是:不依赖字符串过滤,而靠路径归一化 + 白名单根目录约束。任何试图“删掉..”或“替换分号”的做法都不可靠——符号链接、大小写、Unicode、绕过路径等都能轻易突破。
用 realpath 归一化并检查是否在允许范围内
这是最通用、最可靠的做法,适用于所有 POSIX 兼容 shell(bash、dash、zsh 等):
- 先用 realpath -m "$1" 获取绝对、真实、解析后的路径(
-m表示即使路径不存在也返回归一化结果,避免因路径不存在而失败) - 再用 printf "%s
" "$cleaned_path" | grep -q "^/your/allowed/prefix/" 或更安全的字符串前缀判断(如
[[ "$cleaned_path" = "/var/data/"* ]]) - 必须确保白名单前缀以
/开头且结尾不带通配符,避免前缀匹配误判(例如/var会错误匹配/varlog)
拒绝非法字符和危险模式
归一化前可做轻量级预筛,快速拦截明显恶意输入:
- 检查是否含命令注入元字符:[[ "$1" =~ [[:space:]$();&|`\] ]] && { echo "路径含非法字符"; return 1; }
- 禁止空值或仅空白:[ -z "${1##[[:space:]]*}" ] && { echo "路径不能为空"; return 1; }
- 拒绝以
~、$、$(开头的路径(易触发变量展开或命令替换)
校验路径存在性与权限(按需启用)
若函数后续要读/写该路径,应在归一化后进一步验证:
- 存在且为目录:[ -d "$cleaned_path" ] || { echo "目标不是有效目录"; return 1; }
- 可写(如需写入):[ -w "$cleaned_path" ] || { echo "无写入权限"; return 1; }
- 注意:
realpath失败时会报错,应捕获:cleaned_path=$(realpath -m "$1" 2>/dev/null) || { echo "路径解析失败"; return 1; }
避免常见陷阱
这些写法看似合理,实则危险:
-
不用
cd "$1" && pwd—— 若 $1 是../etc; rm -rf /,cd可能失败但后续命令仍可能执行 -
不用
basename/dirname拆解后拼接 —— 无法防御../../../etc/shadow或符号链接绕过 -
不用正则替换
..——....、%2e%2e、Unicode 点字符等均可绕过 -
不信任
pwd或readlink的输出 —— 它们不保证路径真实性和安全性,必须配合realpath -m











