35

On my fedora VM, when running with my user account I have /usr/local/bin in my path:

[justin@justin-fedora12 ~]$ env | grep PATH
 PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/justin/bin

And likewise when running su:

[justin@justin-fedora12 ~]$ su -
Password: 
[root@justin-fedora12 justin]# env | grep PATH
PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/justin/bin

However, when running via sudo, this directory is not in the path:

[root@justin-fedora12 justin]# exit
[justin@justin-fedora12 ~]$ sudo bash
[root@justin-fedora12 ~]# env | grep PATH
PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/sbin:/bin:/usr/sbin:/usr/bin

Why would the path be different when running via sudo?

35

Take a look at /etc/sudoers. The default file in Fedora (as well as in RHEL, and also Ubuntu and similar) includes this line:

Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin

Which ensures that your path is clean when running binaries under sudo. This helps protect against some of the concerns noted in this question. It's also convenient if you don't have /sbin and /usr/sbin in your own path.

  • Ah, I see that in my file. So, not that I want to, but if I added /usr/local/bin to this directive then I would see it in my path when running via sudo, right? – Justin Ethier Mar 5 '11 at 16:25
  • I just tried it and now I see /usr/local/bin. Thank you so much for explaining this! – Justin Ethier Mar 5 '11 at 16:27
  • What about adding your users's path for scripts and binaries, so you don't have to write the absolute path when you must sudo for example a script in your ~/bin (or whatever path you use)? I just made the change - it works, only thought there might be a flip side to it? – Emanuel Berg Oct 15 '12 at 2:01
  • @mattdm Yes, Ubuntu as well, as I came across that issue in Ubuntu Vivid when playing with VM. The same for Debian. – kenorb Dec 24 '15 at 17:22
6

The command su - will execute the root users profile and take on that user's environment including path etc. sudo does not do that.

If you'd like sudo to behave like su - then use the option sudo -i [command which will execute the user's profile

If you'd like su - to behave like sudo then don't use the hyphen - just use su [command]

1

In most linuxes, you install programs via the package management, and get updates in a regular way. If you install something circumventing the package management it will be installed in /usr/local/bin (for example, or .../sbin, or /opt) and not get regular updates.

I guess therefore the programs aren't considered to be that secure, and not put into roots PATH by default.

  • +1 - Cool, I was wondering why it was not in the path, and that makes sense. For what it's worth, I was building node.js from scratch to play around with it, so it makes sense why it would have been put there, and why sudo would exclude this directory by default. – Justin Ethier Mar 5 '11 at 16:29
  • @Justin Ethier: off topic, but see bugzilla.redhat.com/show_bug.cgi?id=634911 – mattdm Mar 6 '11 at 18:53
1

I've just tried this out for myself and I didn't see the behaviour you were seeing - my path remained the same, so maybe your sudo configuration is different. If you check man sudoers you'll see there is an option called secure_path which resets PATH - it sounds like this option might have been enabled.

  • Interesting. This was on Fedora 12, for what it's worth... – Justin Ethier Mar 5 '11 at 16:22
1

Because when you use sudo bash, bash doesn't not act as a login shell. Try again with sudo bash -l and you should see the same result as su -.

If that is correct, then the difference in PATH lies in the configuration files: /etc/profile, ~/.bash_profile, ~/.bash_login, ~/.profile are executed (in that order) for a login shell, while ~/.bashrc is executed for a non-login interactive shell.

1

You can check why (it's different) by the following command:

$ sudo sudo -V | grep PATH
Value to override user's $PATH with: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

as per default security policy plugin in some Linux distributions.

This is further explained in man sudoers:

If the secure_path option is set, its value will be used for the PATH environment variable.

secure_path - Path used for every command run from sudo. If you don't trust the people running sudo to have a sane PATH environment variable you may want to use this.

Another use is if you want to have the “root path” be separate from the “user path”. Users in the group specified by the exempt_group option are not affected by secure_path. This option is not set by default.

If that's the case, you can change that by running sudo visudo and editing the configuration file and modifying your secure_path (adding extra path separated by :) or add your user into exempt_group (so you won't be affected by secure_path options).

Or in order to pass user's PATH temporary, you can run:

sudo env PATH="$PATH" my_command

and you can check that by:

sudo env PATH="$PATH" env | grep ^PATH

See also: How to make sudo preserve $PATH?


Other reason why the environment could be different for sudo, is because you could have env_reset option enabled in your sudoers file. This causes commands to be executed with a new, minimal environment.

So you can use env_keep option (not recommended for security reasons) to preserve your user's environment variables:

Defaults        env_reset
Defaults        env_keep += "PATH PYTHONPATH"
0

Old question, I know, but I stumbled in here just now because I was investigating this exact problem.

For some reason /usr/local/bin was only in the PATH when becoming root via sudo su -. When using sudo -i it wasn't there. Of course I now know I can add it to /etc/sudoers, but that still didn't explain why it is already there after su -. Where did this part of PATH come from?

After a lot of grepping and searching I found the answer:

The default path containing '/usr/local/bin' is actually hardcoded in su(1).

So no pam configuration, profile, bashrc or anything was responsible for selectively adding this element. It was always already there when su took over. And since sudo does not invoke su at all but uses it's own configuration, it was missing after sudo -i

I found this to be true on RHEL6 and RHEL7. I didn't check any other version or distribution.

New contributor
Oscar is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
  • Don't ask me how I verified this.. Okay, if you insist: I hex-edited a copy of the su binary, changed /usr/local/bin into something else and invoked the copy. My PATH now contained the modified string... Good kids and non-lazy sysadmins of course just download the source and check in there. ;-) – Oscar 2 days ago

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.