sudo通过defaults env_keep += "var"白名单机制安全保留指定环境变量,禁用path/home等高危变量,配合secure_path确保命令可执行。

要让 sudo 保留用户原有的特定环境变量,核心不是“全盘继承”,而是通过 /etc/sudoers 中的 Defaults env_keep 有选择地放行那些安全、必要、只读的变量。直接写 env_keep = "PATH HOME" 是危险且不推荐的,容易引发提权风险。
sudo如何用Defaults env_keep保留指定环境变量
env_keep 的作用是在启用 env_reset(默认开启)的前提下,从被清空的原始环境中“白名单式”恢复若干变量。它不复制全部环境,只保留你明确信任的项。
- ✅ 正确做法:用
+=追加,避免覆盖系统默认保留项(如SUDO_COMMAND,TERM等) - ❌ 错误做法:用
=赋值,会清空原有白名单,导致sudo -l或日志功能异常 - ⚠️ 注意:变量必须在当前 shell 中已定义(
echo $HTTP_PROXY有输出),否则env_keep无效
示例配置(用 sudo visudo 编辑):
Defaults env_keep += "LANG LC_CTYPE LC_MESSAGES DISPLAY http_proxy https_proxy no_proxy GOPATH JAVA_HOME"
若需分多行写(如旧版 Ubuntu 14.04 报错),可拆开:
Defaults env_keep += "LANG LC_CTYPE" Defaults env_keep += "DISPLAY http_proxy" Defaults env_keep += "https_proxy no_proxy"
哪些变量可以安全保留
不是所有变量都适合透传。以下类型相对安全,常见于生产环境:
-
语言与区域类:
LANG,LC_*系列(如LC_TIME,LC_NUMERIC),影响文本显示和排序,无执行逻辑 -
图形会话类:
DISPLAY(运行 GUI 程序必需)、XAUTHORITY、COLORTERM -
代理类:
http_proxy,https_proxy,no_proxy(内网合规场景下) -
开发/业务类:
GOPATH,JAVA_HOME,CONFIG_DIR,MYAPP_ENV—— 但需确保其值不含路径拼接或命令片段
禁止保留的变量:PATH, HOME, LD_PRELOAD, LD_LIBRARY_PATH, SHELL, USER —— 它们可能被用于劫持命令查找路径或注入动态库,构成提权入口。
为什么设置了却没生效?常见原因排查
- 用户当前 shell 没导出该变量:运行
echo $http_proxy,若为空,先export http_proxy=...再试 - 使用了
sudo -i或sudo su:它们启动全新 root shell,绕过env_keep;改用sudo -s或sudo command - 存在冲突规则:检查是否同时启用了
Defaults env_delete += "http_proxy"或!env_reset -
sudoers文件语法错误:保存前visudo会校验,但若手动编辑/etc/sudoers后未验证,可能导致部分规则失效
验证是否生效:
sudo env | grep -E '^(LANG|http_proxy|DISPLAY|GOPATH)='
有输出即表示已成功传递。
配合 secure_path 避免命令找不到
有时变量虽保留,但 sudo 找不到对应命令(如 go, java),是因为 secure_path 限制了 PATH 查找范围。需同步更新:
Defaults secure_path = "/usr/local/go/bin:/opt/java/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
注意:这里填绝对路径,不要用 $GOROOT/bin 这类变量。
不复杂但容易忽略











