Linux中sudo默认启用env_reset限制环境变量继承,仅保留TERM、SHELL等安全白名单变量;可通过env_keep精准添加需保留的变量(如LANG、PATH),用env_delete显式删除高危变量(如LD_PRELOAD),-E参数可临时继承全部变量但需SETENV授权。

Linux 中限制 sudo 命令执行时的环境变量,核心是控制子进程启动前继承哪些变量、重置哪些变量,防止因污染环境(如恶意 PATH、LD_PRELOAD)导致提权或绕过。这不是“禁止传入”,而是“有选择地保留”。
默认行为:env_reset 自动启用
现代发行版(如 Ubuntu 22.04+、RHEL 8+)的 /etc/sudoers 默认已开启 Defaults env_reset。这意味着每次执行 sudo 时,会丢弃原始 shell 的绝大多数环境变量,仅保留极少数安全白名单变量(如 TERM、SHELL、USER、LOGNAME、HOME 等)。
你无需手动添加它,但可以确认是否生效:
- 运行
sudo -V | grep "env_reset",若输出含env_reset即表示启用 - 执行
sudo printenv | grep -E '^(PATH|HOME|LANG)',对比普通用户printenv输出,可见变量大幅减少
精准保留必要变量:env_keep
业务场景常需保留某些变量(如语言设置、自定义路径),可通过 env_keep 显式白名单:
- 在 /etc/sudoers 中添加(用
visudo编辑):Defaults env_keep += "LANG LC_* PATH" -
LC_*是通配符,匹配LC_CTYPE、LC_ALL等所有本地化变量 -
+=表示追加到默认白名单,不是覆盖;避免写成=否则会清空系统默认保留项 - 若只对某用户生效,可限定范围:
Defaults:devops env_keep += "PATH"
禁止特定变量传递:!env_delete
当某个变量存在风险(如 LD_PRELOAD 可劫持库调用),即使它未在 env_keep 中,也可能被意外继承(尤其旧版本或误配)。最稳妥方式是显式删除:
- 添加配置:
Defaults env_delete += "LD_PRELOAD LD_LIBRARY_PATH PYTHONPATH" - 该指令优先级高于
env_keep,即使某变量同时出现在两者中,也会被最终删除 - 常见需删除的高危变量:
LD_PRELOAD、LD_LIBRARY_PATH、PS1、BASH_FUNC_*(bash 函数导出)
临时绕过限制(仅限调试,不推荐生产)
某些命令确实依赖完整环境(如开发脚本),可在调用时临时启用,但必须确保权限策略已严格限制该命令本身:
- 用
-E参数继承全部变量:sudo -E /path/to/script.sh - 但前提是 /etc/sudoers 中明确允许该用户对该命令使用
-E:devops ALL=(ALL) SETENV: /path/to/script.sh -
SETENV标签是启用-E的前提,否则 sudo 会拒绝并报错 “sorry, you are not allowed to preserve the environment”











