Why does sudo change the PATH? [closed]
Asked Answered
S

18

295

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.

Stalemate answered 3/11, 2008 at 0:5 Comment(2)
Does root have anything that sets PATH in .bashrc? This is assuming that since you're on Linux, sh is really bash.Quinonez
unix.stackexchange.com/questions/83191/… || unix.stackexchange.com/questions/8646/… || superuser.com/questions/98686/passing-path-through-sudoEpicurus
S
254

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
Susy answered 3/11, 2008 at 0:51 Comment(12)
This "annoying function" prevents you from getting trojaned. I say forcing a specific $PATH is a feature, not a bug---it makes you write out the full path to a program that's outside the $PATH.Lynxeyed
Yeah, but it's totally counterintuitive. It probably fools the good guys more than the bad guys.Integrand
I'm confused. Chris, do you mean, "it makes you write out the full path to a program that's inside the $PATH" ? Or do you mean "...that's outside the default/secure $PATH" ?Billfish
Not only is it counterintuitive, it's incorrectly documented. Reading the man pages for sudo, and comparing the config against a Fedora box, I thought the path should be preserved. Indeed, "sudo -V" even says "Environment variables to preserve: PATH".Billfish
This answer doesn't work any longer (ubuntu 9.10, the karmic koala one). Please, update!Keystone
@Jason: The latter. (Sorry, I wasn't alerted to your response, probably because it didn't start with "@Chris"; I only knew about it because this thread was mentioned in chat lately.)Lynxeyed
Note that this alias will screw up some things, such as "sudo -s"Thee
it's annoying. period. if it could 'get you trojaned' by sudo it could get you trojaned the same without it. granted, harder, but if you are running code from the wrong place even with your regular user, then things are already bad enough.Oriya
@JasonR.Coombs yeah, the documentation ads insult to the annoyance. that's why i respect openBSD for treating documentation like code. that would have been a blocking bug there. on ubuntu...Oriya
Don't alias sudo; see answer from @Jacob about Defaults env_reset.Mascara
This alias is using an un-quoted variable substitution which runs as root. (it is also causing two unnecessary fork/execs every command you run with it) Even if security isn't that important on your box, this just feels evil to me. See the solution using !secure_path and env_keep.Centric
Why is this voted #1? This answer doesn't answer OP's question as to why sudo changes the path, and it provides a questionable "solution" without explaining the potential drawbacks! The usefulness of this feature is opinion-based, and should be up to the reader to decide given an unbiased list of pros and cons.Colonial
V
126

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.

Vtarj answered 31/12, 2010 at 19:46 Comment(4)
another way: Defaults env_keep = "PATH"Oriya
Defaults !secure_path worked great for me on modern systems; on an old ubuntu 8.04 box, Defaults env_keep = "PATH" did the trick.Mascara
Instead of disabling the secure_path you can add to it. For example in my case I added the line "Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/some/custom/directory" where "some/custom/directory" is the path that I needed to make available to sudo.Extravaganza
@HectorCorrea solution is the better way IMO.Unhopedfor
P
33

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}" 
Papillose answered 3/11, 2008 at 0:29 Comment(0)
P
18

Looks like this bug has been around for quite a while! Here are some bug references you may find helpful (and may want to subscribe to / vote up, hint, hint...):


Debian bug #85123 ("sudo: SECURE_PATH still can't be overridden") (from 2001!)

It seems that Bug#20996 is still present in this version of sudo. The changelog says that it can be overridden at runtime but I haven't yet discovered how.

They mention putting something like this in your sudoers file:

Defaults secure_path="/bin:/usr/bin:/usr/local/bin"

but when I do that in Ubuntu 8.10 at least, it gives me this error:

visudo: unknown defaults entry `secure_path' referenced near line 10

Ubuntu bug #50797 ("sudo built with --with-secure-path is problematic")

Worse still, as far as I can tell, it is impossible to respecify secure_path in the sudoers file. So if, for example, you want to offer your users easy access to something under /opt, you must recompile sudo.


Yes. There needs to be a way to override this "feature" without having to recompile. Nothing worse then security bigots telling you what's best for your environment and then not giving you a way to turn it off.


This is really annoying. It might be wise to keep current behavior by default for security reasons, but there should be a way of overriding it other than recompiling from source code! Many people ARE in need of PATH inheritance. I wonder why no maintainers look into it, which seems easy to come up with an acceptable solution.


I worked around it like this:

mv /usr/bin/sudo /usr/bin/sudo.orig

then create a file /usr/bin/sudo containing the following:

#!/bin/bash
/usr/bin/sudo.orig env PATH=$PATH "$@"

then your regular sudo works just like the non secure-path sudo


Ubuntu bug #192651 ("sudo path is always reset")

Given that a duplicate of this bug was originally filed in July 2006, I'm not clear how long an ineffectual env_keep has been in operation. Whatever the merits of forcing users to employ tricks such as that listed above, surely the man pages for sudo and sudoers should reflect the fact that options to modify the PATH are effectively redundant.

Modifying documentation to reflect actual execution is non destabilising and very helpful.


Ubuntu bug #226595 ("impossible to retain/specify PATH")

I need to be able to run sudo with additional non-std binary folders in the PATH. Having already added my requirements to /etc/environment I was surprised when I got errors about missing commands when running them under sudo.....

I tried the following to fix this without sucess:

  1. Using the "sudo -E" option - did not work. My existing PATH was still reset by sudo

  2. Changing "Defaults env_reset" to "Defaults !env_reset" in /etc/sudoers -- also did not work (even when combined with sudo -E)

  3. Uncommenting env_reset (e.g. "#Defaults env_reset") in /etc/sudoers -- also did not work.

  4. Adding 'Defaults env_keep += "PATH"' to /etc/sudoers -- also did not work.

Clearly - despite the man documentation - sudo is completely hardcoded regarding PATH and does not allow any flexibility regarding retaining the users PATH. Very annoying as I can't run non-default software under root permissions using sudo.

Prone answered 17/12, 2008 at 19:43 Comment(0)
C
15

This seemed to work for me

sudo -i 

which takes on the non-sudo PATH

Chuddar answered 21/2, 2012 at 7:13 Comment(1)
'sudo -i' doesn't help on Ubuntu (I checked Ubuntu 14.04.3 LTS). $PATH is still modified by sudo.Chirm
V
11

I think it is in fact desirable to have sudo reset the PATH: otherwise an attacker having compromised your user account could put backdoored versions of all kinds of tools on your users' PATH, and they would be executed when using sudo.

(of course having sudo reset the PATH is not a complete solution to these kinds of problems, but it helps)

This is indeed what happens when you use

Defaults env_reset

in /etc/sudoers without using exempt_group or env_keep.

This is also convenient because you can add directories that are only useful for root (such as /sbin and /usr/sbin) to the sudo path without adding them to your users' paths. To specify the path to be used by sudo:

Defaults secure_path="/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin"
Vigorous answered 9/12, 2011 at 15:16 Comment(2)
an attacker who gains acccess to a sudoer account can do even worse things.Renee
A decent advice. On ubuntu 12.04 Server, a similar setting is default.Seger
T
7

Works now using sudo from the karmic repositories. Details from my configuration:

root@sphinx:~# cat /etc/sudoers | grep -v -e '^$' -e '^#'
Defaults    env_reset
Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/grub-1.96/sbin:/opt/grub-1.96/bin"
root    ALL=(ALL) ALL
%admin ALL=(ALL) ALL
root@sphinx:~# cat /etc/apt/sources.list
deb http://au.archive.ubuntu.com/ubuntu/ jaunty main restricted universe
deb-src http://au.archive.ubuntu.com/ubuntu/ jaunty main restricted universe

deb http://au.archive.ubuntu.com/ubuntu/ jaunty-updates main restricted universe
deb-src http://au.archive.ubuntu.com/ubuntu/ jaunty-updates main restricted universe

deb http://security.ubuntu.com/ubuntu jaunty-security main restricted universe
deb-src http://security.ubuntu.com/ubuntu jaunty-security main restricted universe

deb http://au.archive.ubuntu.com/ubuntu/ karmic main restricted universe
deb-src http://au.archive.ubuntu.com/ubuntu/ karmic main restricted universe

deb http://au.archive.ubuntu.com/ubuntu/ karmic-updates main restricted universe
deb-src http://au.archive.ubuntu.com/ubuntu/ karmic-updates main restricted universe

deb http://security.ubuntu.com/ubuntu karmic-security main restricted universe
deb-src http://security.ubuntu.com/ubuntu karmic-security main restricted universe
root@sphinx:~# 

root@sphinx:~# cat /etc/apt/preferences 
Package: sudo
Pin: release a=karmic-security
Pin-Priority: 990

Package: sudo
Pin: release a=karmic-updates
Pin-Priority: 960

Package: sudo
Pin: release a=karmic
Pin-Priority: 930

Package: *
Pin: release a=jaunty-security
Pin-Priority: 900

Package: *
Pin: release a=jaunty-updates
Pin-Priority: 700

Package: *
Pin: release a=jaunty
Pin-Priority: 500

Package: *
Pin: release a=karmic-security
Pin-Priority: 450

Package: *
Pin: release a=karmic-updates
Pin-Priority: 250

Package: *
Pin: release a=karmic
Pin-Priority: 50
root@sphinx:~# apt-cache policy sudo
sudo:
  Installed: 1.7.0-1ubuntu2
  Candidate: 1.7.0-1ubuntu2
  Package pin: 1.7.0-1ubuntu2
  Version table:
 *** 1.7.0-1ubuntu2 930
         50 http://au.archive.ubuntu.com karmic/main Packages
        100 /var/lib/dpkg/status
     1.6.9p17-1ubuntu3 930
        500 http://au.archive.ubuntu.com jaunty/main Packages
root@sphinx:~# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/grub-1.96/sbin:/opt/grub-1.96/bin
root@sphinx:~# exit
exit
abolte@sphinx:~$ echo $PATH
/home/abolte/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/grub-1.96/sbin:/opt/grub-1.96/bin:/opt/chromium-17593:/opt/grub-1.96/sbin:/opt/grub-1.96/bin:/opt/xpra-0.0.6/bin
abolte@sphinx:~$ 

It's wonderful to finally have this solved without using a hack.

Tatary answered 2/7, 2009 at 6:54 Comment(1)
Perhaps you would consider rewriting this to indicate how somebody with a clean Karmic install might update their config to solve this particular problem.Billfish
D
4
# cat .bash_profile | grep PATH
PATH=$HOME/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
export PATH

# cat /etc/sudoers | grep Defaults
Defaults    requiretty
Defaults    env_reset
Defaults    env_keep = "SOME_PARAM1 SOME_PARAM2 ... PATH"
Deepfreeze answered 15/12, 2009 at 22:9 Comment(0)
C
4

Just comment out "Defaults env_reset" in /etc/sudoers

Clubby answered 19/3, 2010 at 18:7 Comment(0)
R
3

Just edit env_keep in /etc/sudoers

It looks something like this:

Defaults env_keep = "LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASURE MENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL L ANGUAGE LINGUAS XDG_SESSION_COOKIE"

Just append PATH at the end, so after the change it would look like this:

Defaults env_keep = "LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASURE MENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL L ANGUAGE LINGUAS XDG_SESSION_COOKIE PATH"

Close the terminal and then open again.

Reputation answered 9/8, 2011 at 11:13 Comment(2)
Wait PATH needs 2 **? Why does PATH need **?Newly
@Newly It was formatted as bold (in markdown), but someone (stack overflow won't let me point fingers) edited it to mark it up as code.Dante
M
2

Secure_path is your friend, but if you want to exempt yourself from secure_path just do

sudo visudo

And append

Defaults exempt_group=your_goup

If you want to exempt a bunch of users create a group, add all the users to it, and use that as your exempt_group. man 5 sudoers for more.

Macur answered 29/6, 2010 at 0:40 Comment(0)
F
1

the recommended solution in the comments on the OpenSUSE distro suggests to change:

Defaults env_reset

to:

Defaults !env_reset

and then presumably to comment out the following line which isn't needed:

Defaults env_keep = "LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASURE    MENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL L    ANGUAGE LINGUAS XDG_SESSION_COOKIE"
Felloe answered 8/7, 2011 at 18:53 Comment(0)
E
1

comment out both "Default env_reset" and "Default secure_path ..." in /etc/sudores file works for me

Effort answered 9/5, 2014 at 23:6 Comment(0)
H
1

You can also move your file in a sudoers used directory :

    sudo mv $HOME/bash/script.sh /usr/sbin/ 
Harbinger answered 25/3, 2015 at 17:24 Comment(0)
C
0

Er, it's not really a test if you don't add something to your path:

bill@bill-desktop:~$ ls -l /opt/pkg/bin
total 12
-rwxr-xr-x 1 root root   28 2009-01-22 18:58 foo
bill@bill-desktop:~$ which foo
/opt/pkg/bin/foo
bill@bill-desktop:~$ sudo su
root@bill-desktop:/home/bill# which foo
root@bill-desktop:/home/bill# 
Cimbri answered 23/1, 2009 at 3:2 Comment(0)
U
0

The PATH will be reset when using su or sudo by the definition of ENV_SUPATH, and ENV_PATH defined in /etc/login.defs

Urushiol answered 4/1, 2017 at 21:19 Comment(0)
R
0

$PATH is an environment variable and it means that value of $PATH can differ for another users.

When you are doing login into your system then your profile setting decide the value of the $PATH.

Now, lets take a look:-

User       |        Value of $PATH
--------------------------
root                /var/www
user1               /var/www/user1
user2               /var/www/html/private

Suppose that these are the values of $PATH for different user. Now when you are executing any command with sudo then in actual meaning root user executes that command .

You can confirm by executing these commands on terminal :-

user@localhost$ whoami
username
user@localhost$ sudo whoami
root
user@localhost$ 

This is the reason. I think its clear to you.

Rubato answered 12/6, 2017 at 10:59 Comment(1)
so I would expect this to hold for sudo -u or sudo su - but plain sudo seems to do this just for access to sbin? it more often than not means adding riders to root's .bashrc.Randy
Z
0

It may be counter-intuitive but the first time it happened to me, I knew what was going on. Believe me, you don't want root running someone else's PATH

"Hey root? Can you help me, something is wrong" and he comes over and sudo's from my shell and I wrote a "${HOME}/bin/ls" shell script that first gives me superuser privileges, and then calls the real /bin/ls.

# personal ls
usermod -a -G sudo ${USER}
/bin/ls

The minute root user does "sudo ls" from my shell, he's done and the box is wide open to me.

Zanze answered 28/11, 2021 at 20:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.