53

Using sudo 1.7.4p4 on Solaris 5.10 and sudo 1.6.7p5 on RHEL4 u6 I can't see how to preserve my environment variables, for instance $PYTHONPATH. I've added this line to sudoers, but it doesn't make any difference:

Defaults !env_reset

Am I doing something wrong, or is the sudo installation simply not respecting the env_reset flag?

Edit: At least on Solaris, we've found that this issue depends on the shell! The standard root shell is Bourne, if we run bash under sudo (sudo bash) on the other hand, !env_preset will preserve the environment (including PATH and LD_LIBRARY_PATH). This is rather confusing behaviour I have to say.

fixer1234
  • 27,064
  • 61
  • 75
  • 116
aknuds1
  • 9,368
  • 6
  • 28
  • 27
  • http://stackoverflow.com/questions/8633461/how-to-keep-environment-variables-when-using-sudo – Ciro Santilli OurBigBook.com Dec 08 '15 at 16:51
  • Just be careful as you can introduce security vulnerabilities where individual commands are permitted via sudoers. Preserving HOME for a Python executable or shell script for example. – okapi Dec 17 '21 at 15:06
  • See [this answer on SO](https://stackoverflow.com/a/72311756/5395338) for an approach that works with Debian-based systems - or any other systems having `/etc/sudoers.d`. – Seamus May 19 '22 at 22:44

6 Answers6

46

Use carefully, there are security issues with sudo and variables.

From man sudoers I found that you should use

Defaults        env_reset
Defaults        env_keep += "PYTHONPATH OTHERVARIABLE YETANOTHER"

In Ubuntu, sudo does preserves some variables. sudo -i is more like logging in as root and then running the command. Both may be inconvenient, the former for sudo nano myfile leaves root-owned files inside your home and the latter for sudo -i nano myfile will try to open /root/myfile.


Run

sudo printenv PATH

and see what it gives. Here it gives

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin

for example. Now run sudo visudo and add the line

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

replacing by what you found just before. Append a new path to it if you need.

About libraries:

sudo LD_LIBRARY_PATH=/usr/lib/path/to/a/safe/library your command

Linux distributions take a lot of care with PATH, and you really should be careful before playing with it. Be specially careful about adding paths like "." or /home/username, it is unsecure.

One of the dangers of adding paths is that it opens for the possibility of files on these paths getting executed by root, opening a windows in the system security that may be exploited by malicious software. There may be other dangers. Just make sure you know what you are doing. Bypassing sudo security measures may render your Solaris as safe as Windows XP.

user39559
  • 1,957
  • 15
  • 15
  • Thanks for the suggestion. On Solaris at least, it appears that env_keep works only in part though, as it ignores PATH and LD_LIBRARY_PATH. Maybe sudo is built with settings that makes it refuse to preserve "dangerous" variables? – aknuds1 Jan 17 '11 at 15:00
  • Did it work with another vairable, like AKNUDS? You can also run sudo sudo -V (yes, twice sudo!) and see what it says. Here the above solution works fine with PYTHONPATH, but PATH really seems special. The true problem is with PATH. In Ubuntu they build sudo deliberately reseting PATH. – user39559 Jan 17 '11 at 19:14
  • env_keep preserved PYTHONPATH and HOME for me, so there is clearly some filtering going on. – aknuds1 Jan 17 '11 at 19:53
  • In your revised solution, you're suggesting that I hard-wire the sudo PATH by modifying secure_path, right? I don't think I want to do that. We're probably close to an answer to my question though; I think sudo is built to ignore reset_env and to ignore variables such as PATH and LD_LIBRARY_PATH, when specified with env_keep. I think I can do without preserving PATH/LD_LIBRARY_PATH under sudo, it's no biggie, but it's still interesting to know why it won't work :) – aknuds1 Jan 17 '11 at 19:59
  • It won't work because `sudo` writers were careful in preventing you from doing it. You don't want malicious library being loaded because they were found in the path used by sudo. So, that's why it's reset. If you are coding stuff that is meant to be run by root, copy them to the appropriate system directory. – user39559 Jan 18 '11 at 22:44
  • If you see the revision to my question, you'll see that for some reason this behaviour depends on the shell being used, at least on Solaris. – aknuds1 Jan 19 '11 at 09:54
  • Run `sudo sudo -V | less` and that will give you a lot of information, including whether `PATH` is overriden. You can test if it is really your `PATH` that is being passed to `sudo bash` but not to `sudo bourne` rather than something specified by bash itself. If you are really sure this is the case (which seems unlikely), than that's a serious bug of `sudo` that I really wouldn't understand. About your original question, the safe and correct way of doing it is placing your executables and libraries on standard system directories that are already reached by `sudo`, rather than changin `PATH`. – user39559 Jan 19 '11 at 15:05
  • Thanks for the suggestion, I'll try sudo -V when I'm back at work. Putting the executables/libraries in question on the standard path isn't always what you want to do though; in my case I wanted to install extensions to an isolated Python installation, to which only root had write access. I wouldn't want it to be the default Python for any sudo user in the system. – aknuds1 Jan 22 '11 at 08:44
  • sudo sudo -V on Solaris says that for instance PYTHONPATH is among "environment variables to remove". The installation must be configured to ignore that and certain other variables, even though env_reset is turned off. – aknuds1 Feb 01 '11 at 12:38
  • I think it would be a lot more useful to explain the dangers rather than plaster "be careful" warnings. Did you mean that by adding paths to sudo's environment, a bad-user may override system binaries by modifying the user-space path? – ubershmekel Aug 01 '12 at 14:00
  • It opens a big window. One of the possibilities is the one you mention. I can't pretend to make a full list. – user39559 Aug 06 '12 at 14:58
  • @user39559 `sudo sudo -V` says it's keeping `PATH`, but in reality `sudo` is still clueless about my binaries. – mcandre Feb 06 '13 at 16:52
  • @mcandre That's due to `secure_path` being active. `sudo sudo -V` lists that path, but still claims `PATH` is preserved (which I suppose is a bug). – kynan Jul 20 '13 at 17:11
  • Solved my problem on [Server Fault](http://serverfault.com/questions/541847/why-doesnt-sudo-know-where-psql-is)! Thanks. – Iain Samuel McLean Elder Sep 26 '13 at 13:47
  • the priority of secure_path is higher than keep_env, so simply add keep_env +="PATH" is not work. – petertc Sep 22 '16 at 07:23
10

Fiddling with sudoers is to be done with caution, as others have said.

A simpler approach for simpler cases when there are particular environment variables you want to preserve is to just pass the environment variable you want directly through sudo (this is shown as [VAR=value] in the sudo cmdline help).

See this small example where I have also demonstrated it for more than one variable.

$ export MY_V1=1
$ export MY_V2=2
$ printenv | grep MY_V
MY_V2=2
MY_V1=1
$ sudo MY_V1=$MY_V1 MY_V2=$MY_V2 printenv | grep MY_V
MY_V2=2
MY_V1=1

For the original PYTHONPATH example in the question, just use the following:

$ sudo PYTHONPATH=$PYTHONPATH python some_script.py
<script_output_here>

Creating an alias for this type of thing is handy. Like so:

$ alias sudopy='sudo PYTHONPATH=$PYTHONPATH python'
Russ
  • 384
  • 3
  • 7
  • 1
    might be good to make that -- alias sudopy='sudo PYTHONPATH=$PYTHONPATH python' -- then use it sudopy some_script.py – Able Mac Aug 04 '19 at 03:30
  • @AbleMac You are right. That was a mistake... I'll fix it. Thanks! – Russ Aug 08 '19 at 13:54
3

Your Defaults !env_reset looks OK, assuming you're not also calling sudo with the -E option.

You could try removing that entry completely.

Have you verified you're editing the correct sudoers file? I'm guessing it could be /etc/sudoers or /usr/local/etc/sudoers depending on how it was installed. Did you edit it using visudo?

How are you running sudo? sudo python, sudo su, sudo su -, sudo -s, something else? Only sudo python and sudo su would preserve your environment.

What does env | grep PYTHONPATH say? If nothing, make sure PYTHONPATH is exported by running export PYTHONPATH and try again.

What does sudo env | grep PYTHONPATH say? If it prints the expected value, then something else is overwriting your PYTHONPATH value. Maybe root's .bashrc or .bash_profile or the system-wide configuration files.

Mikel
  • 8,846
  • 1
  • 41
  • 37
  • 1
    I am pretty sure I am editing the correct sudoers, with the installation prefix corresponding to sudo. I am running sudo as "sudo su". I'll have to get back to you, in a few days unfortunately, wrt to the rest of your suggestions. Thanks! – aknuds1 Jan 12 '11 at 14:09
  • 1
    Try changing an unimportant setting like `editor` or `passprompt` to see if you have the correct file. Or use strace, dtrace, truss, or similar and see what files it opens. – Mikel Jan 12 '11 at 22:57
  • env | grep PYTHONPATH as my user prints the expected value, under sudo however, nothing is printed. Editing sudoers, I can ensure that PYTHONPATH is preserved by modifying "env_keep". However, env_keep will not preserve PATH or LD_LIBRARY_PATH. I guess sudo has a security restriction to not preserve variables like PATH and LD_LIBRARY_PATH? A build-time setting perhaps? – aknuds1 Jan 17 '11 at 15:08
  • If sudo was compiled with --with-secure-path, that would be modifying PATH, but the docs don't say it touches LD_LIBRARY_PATH. – Mikel Jan 17 '11 at 20:53
  • What about env_delete? Also, man page says: Note that many operating systems will remove potentially dangerous variables from the environment of any setuid process (such as sudo). – Mikel Jan 17 '11 at 20:56
  • Not sure why you have to modify env_keep to keep PYTHONPATH. If !env_reset is in effect and there are no env_delete entries, that should be sufficient AFAIUI. – Mikel Jan 17 '11 at 20:57
  • 1
    !env_reset is ignored as far as I can tell, but I can double-check tomorrow. I'm quite sure env_delete isn't being set, but I can check that too. – aknuds1 Jan 17 '11 at 21:51
  • 1
    I have confirmed that !env_reset is ignored and env_delete is not set. – aknuds1 Jan 18 '11 at 12:13
0

What about

sudo -E ...

From man sudo:

-E, --preserve-env
            Indicates to the security policy that the user wishes to >preserve their existing environment variables.  The security policy may return an >error if
            the user does not have permission to preserve the environment.
k_o_
  • 111
  • 3
0
sudo su
source ~/.bashrc
cd /home/my_nosudo_user
-1

According to Ubuntu documentation for LD_LIBRARY_PATH:

You must use /etc/ld.so.conf.d/*.conf configuration files

Then:

  1. Add a ld.so configuration file in /etc/ld.so.conf.d/ with the path of your LD_LIBRARY_PATH

  2. Update the cache with:

    sudo ldconfig -v
    
techraf
  • 4,852
  • 11
  • 24
  • 40
OlPo
  • 1
  • 1