Why does sudo change the PATH?

This is the PATH variable without sudo:

$ echo 'echo $PATH' | sh 
/opt/local/ruby/bin:/usr/bin:/bin

This is the PATH variable with sudo:

$ echo 'echo $PATH' | sudo sh
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin

As far as I can tell, sudo is supposed to leave PATH untouched. What's going on? How do I change this? (This is on Ubuntu 8.04).

UPDATE: as far as I can see, none of the scripts started as root change PATH in any way.

From man sudo:

To prevent command spoofing, sudo checks ``.'' and ``'' (both denoting current directory) last when searching for a command in the user's PATH (if one or both are in the PATH). Note, however, that the actual PATH environment variable is not modified and is passed unchanged to the program that sudo executes.


This is an annoying function a feature of sudo on many distributions.

To work around this "problem" on ubuntu I do the following in my ~/.bashrc

alias sudo='sudo env PATH=$PATH'

Note the above will work for commands that don't reset the $PATH themselves. However `su' resets it's $PATH so you must use -p to tell it not to. I.E.:

sudo su -p

In case someone else runs accross this and wants to just disable all path variable changing for all users.
Access your sudoers file by using the command:visudo. You should see the following line somewhere:

Defaults env_reset

which you should add the following on the next line

Defaults !secure_path

secure_path is enabled by default. This option specifies what to make $PATH when sudoing. The exclamation mark disables the feature.


PATH is an environment variable, and as such is by default reset by sudo.

You need special permissions to be permitted to do this.

From man sudo

       -E  The -E (preserve environment) option will override the env_reset
           option in sudoers(5)).  It is only available when either the match-
           ing command has the SETENV tag or the setenv option is set in sudo-
           ers(5).
       Environment variables to be set for the command may also be passed on
       the command line in the form of VAR=value, e.g.
       LD_LIBRARY_PATH=/usr/local/pkg/lib.  Variables passed on the command
       line are subject to the same restrictions as normal environment vari-
       ables with one important exception.  If the setenv option is set in
       sudoers, the command to be run has the SETENV tag set or the command
       matched is ALL, the user may set variables that would overwise be for-
       bidden.  See sudoers(5) for more information.

An Example of usage:

cat >> test.sh
env | grep "MYEXAMPLE" ;
^D
sh test.sh 
MYEXAMPLE=1 sh test.sh
# MYEXAMPLE=1
MYEXAMPLE=1 sudo sh test.sh 
MYEXAMPLE=1 sudo MYEXAMPLE=2 sh test.sh 
# MYEXAMPLE=2

update

man 5 sudoers : 

     env_reset       If set, sudo will reset the environment to only contain
                       the LOGNAME, SHELL, USER, USERNAME and the SUDO_* vari-
                       ables.  Any variables in the caller's environment that
                       match the env_keep and env_check lists are then added.
                       The default contents of the env_keep and env_check
                       lists are displayed when sudo is run by root with the
                       -V option.  If sudo was compiled with the SECURE_PATH
                       option, its value will be used for the PATH environment
                       variable.  This flag is on by default.

So may need to check that this is/is not compiled in.

It is by default in Gentoo

# ( From the build Script )
....
ROOTPATH=$(cleanpath /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/bin${ROOTPATH:+:${ROOTPATH}})
....
econf --with-secure-path="${ROOTPATH}"