How do I protect my environment from sudo erasing half of it?

It seems I can protect variables, but functions that the variables (like the prompt, for example) rely on are undefined.

This means that the next time the prompt is displayed, instead of running a read-only function in the environment, it will search for the executable on disk and execute the first thing it finds.

This may or may not be harmful depending on the circumstance, but it seems that preserving "half" of the environment and deleting things relied on in, even, for example, to display the next prompt, is a recipe for disaster.

Also, on installations where the env IS cleared, variables like 'TERM' are preserved, but not 'DISPLAY'. Aren't GUI's a bit more common these days than TTY's? Possibly worse is that sudo encourages the use of the "auth-time-only" pam_env function. In pam_env's documentation, it is recommended for use only during the first authorization to the system, since if the user comes in from a remote system, that is the only time pam can access where the user has logged in from and set things like REMOTEHOST and DISPLAY. With sudo wiping out the login trail and telling distro's to use pam_env, it all but guarantees that the original user's host and display will be cleared. Besides obfuscating the user's origin, it also kills any remote login session.

Considering that many systems don't allow you to login to root directly via a remote session -- but require you to login via your user, then sudo to root, this would seem to be a clear way to nullify this security model.

Is there another version of sudo that isn't so insecure?


For prompt, 1) I don't want to call disk based functions each time I prompt (as your switching colors does). Also requirement: when I list out my global vars, OR when I am tracing, I don't want the color switch codes to be displayed in the raw and change colors where not desired.

Also I didn't want to make this about my specific setup, as it's been working for YEARS across multiple unixes and Windows, only to need "fixing" now that sudo can't copy my environment with integrity.

For the color setting, that's relatively trivial. Use "read" and read in the codes from tput into vars, so listed or in trace, the codes are in unexpanded bash input. Example:

read _CRST <<<"$(tput sgr0)"   #Reset
read _CRed <<<"$(tput setaf 1)"  #Red
read _CBLD <<<"$(tput bold)"   #Bold

becomes: _CBLD=$'\E[1m' _CRST=$'\E[0;10m' _CRed=$'\E[31m'

Note: my requirements have been developed and refined over several years, this isn't a spur of the moment creation.

But for the prompt, that's way more complex -- remember, no host for local host, but also want it in the window title.

Everything but the "spwd" is here: # build a prompt ########### #specific to xterm & linux console compat emulations read _CRST <<<"$(tput sgr0)" #Reset read _CRed <<<"$(tput setaf 1)" #Red read _CBLD <<<"$(tput bold)" #Bold declare _prompt_open="" _prompt_close="" _prompt=">" declare _disp_port=${DISPLAY/[^:]*:/} printf -v qUSER "%q" $USER typeset -x qUSER

[[ $UID -eq 0 ]] && { 
PS1='\['"$_prompt_open"'\]$(spwd "$PWD" )'"$_prompt"'\['"$_prompt_close"'\] ';

if [[ -n ${REMOTEHOST:-""} ]]; then
    function titlebar { \
        printf "\033]1;${qUSER}@${HOSTNAME}:%q\007" "$(spwd "$PWD")" ;\
    export -f titlebar

    PS1='\[$(titlebar)'"$_prompt_open"'\]${HOSTNAME}:$(spwd "$PWD")'"$_prompt"'\['"$_prompt_close"'\] '

FWIW, PS4 gets this:


Notice that the spwd func isn't in the above, -- it's in a separate file that is only sourced when a new environment is initialized.

But that function and it's data are : if [[ ! ${qUSER:-""} ]]; then printf -v qUSER "%q" $USER export qUSER fi export _home_prefix=${HOME%/*}/

Next func idea came from suse, but was completely rewritten.

Return a shorted path when displayed path takes up > 50% width of screen:

alias int=declare\ -i _e=echo _pf=printf exp=export ret=return 
exp __dpf__='local -a PF=(
                "..." )'
function spwd () {  \
  (($#)) || { _e "spwd called with null arg"; return 1; }; \
  int w=COLUMNS/2                         ;\
  ( _pf -v _p "%s" "$1" ; export IFS=/    ;\
    set $_p; shift; unset IFS             ;\
    t="${_p#$_home_prefix}"               ;\
    int tl=${#t}                          ;\
    if (($#<=6 && tl<w));then ((tl<=2)) && \
      { _e -En "${_p}";return 0; }        ;\
    else                                   \
      eval "$__dpf__"                     ;\
      int i pfl=${#PF[*]}                 ;\
      for ((i=0; i<pfl; ++i)); do eval     \
        "_pf -v _pa %s \"${PF[i]}\""      ;\
        _p="$(eval "_pf %s \"$_pa\"")"    ;\
        ((${#_p}<w)) && break;  done      ;\
    fi                                    ;\
    _e -En "${_p#$_home_prefix}" )    

typeset -xrf spwd

On resourcing read-only values or functions:

If you try to re-source read-only variables or functions, you get an error. Since the variables are still readonly ... it is only when sudo destroys over half the environment that the read-only functions could be safely read in . In all other cases, reading them in again would result in multiple runtime errors (can't redefine a readonly var or function).

My routines would have to somehow know that half of the read-only values in memory (those that look like functions) were deleted and only read them. I am not sure how I would code in hacks to test for overwritten read-only vars or functions -- nor should I have to.

As for overriding my functions:

1) a persistent user wouldn't have sudo access in the first place. 2) Since I'm the system admin, these features are for me... if I hack my own system, "C'est la vie'.

re: PAM: Yes, sudo uses pam as most distros configure.

All I want is for sudo to do what it says: and not touch my environment when I tell it not to. That it has no option for such is why I asked about a more secure replacement. Programs that "help" the user by taking away their configuration choices are not good security programs, as they don't respect the local site's security policy, but instead, override it because they think they know better. I have yet to see such a program be correct.

Hopefully this answers your questions about why I am asking how to get around this problem and why it is a problem, though that certainly goes significantly beyond the asking of a question that someone already marked down even being ASKED... (how dare I!)...

  • When I ask it to preseve the environment, it doesn't. It wipes out the functions which are part of the environment. It doesn't follow it's config file. Because of that, when the prompt is printed, it goes off and looks for files to run as soon as you sudo to root --- because the environment-functions are all deleted.
    – Astara
    Aug 5 '14 at 11:05

you've sent this to the sudo mailing list also, didn't you?

Environment variables

Well, in sudoers you can configure which environment variables it should keep. Take a loop at Defaults env_reset and env_keep. These can also be set per user or group. Just add REMOTEHOST and DISPLAY and hey, presto.


Why are you using functions in your prompt?

++ It seems that you want your prompt to be something like this:

PS1='${REMOTEHOST}${REMOTEHOST+->}\u@\h:\w\$ '

This is of course not switching colors. To do that:

PS1='\[$(tput bold)$(tput setaf 1)${REMOTEHOST}${REMOTEHOST+->}\u@\h:\w\$$(tput sgr0) \]'

Source functions

And why don't you re-source the file containing these functions?

++ You're saying that you do, yet you're using flags to optimize the functions and prevent them from being reread. If you leave that optimization out, does it work then?

Readonly functions

And w.r.t. root, why would you keep functions in an environment that could be changed by a user? As root, you need a well defined environment, set up without any influence from the user switching to root.

++ A persistent user can always reset everything in a shell. Point being, you can't rely on functions to stay the same. So you have to source them each and every time from a reliable location.


And sudo doesn't use pam_env() in it's source. It is called, however through the PAM stack. So, can you provide a link supporting your claim?

++ Yes, sudo can use PAM, if you so configure.

Kind regards, Edgar.

  • Why are you not using functions in your prompt? How do you display the host you log'ed in from, in the prompt, on the window title, a relevant path -- trimmed down if too long based on screen size, changes to use "#" instead of ">" and appears in red? Good security is about awareness of your environment as much as mindless rules.
    – Astara
    Aug 5 '14 at 10:50
  • I do source the files with the functions in them. Since they are part of the environment, a flag is set when they a read in to indicate they are already red in so shells later on don't reread variables and functions that may be read-only and get errors. The problem is sudo has no option to pass through an uncorrupted environment. You can toss it out completely, or have it half way corrupted with any functional environment variables deleted.
    – Astara
    Aug 5 '14 at 10:52
  • As for a link supporting a claim of sudo using pam -- you need to read the changelog.... a bit more often: rpmfind.net/linux/RPM/opensuse/12.2/x86_64/… ....* Wed May 16 2012 vcizek@suse.com - update to 1.8.5 Some of the changes: * /etc/environment is no longer read directly on Linux systems when PAM is used. Sudo now merges the PAM environment into the user's environment which is typically set by the pam_env module. ....it was changed over 2 years ago...
    – Astara
    Aug 5 '14 at 10:59
  • Why would I keep read-only functions in my environment set by the system login scripts? And how are those changed? How do you change read-only scripts.... and I am the user switching to root. Not some random joe... I want it to be seamless when I need it. I don't need it zeroing parts of my environment or resetting my display (standard in suse since 12.2, at least)... While I've fixed that on my machine -- many others have complained bout the new behaviors as well
    – Astara
    Aug 5 '14 at 11:03
  • Re: "+ A persistent user can always reset everything in a shell. Point being, you can't rely on functions to stay the same. So you have to source them each and every time from a reliable location." You can use the same argument to apply to any/all environment variables... I.e. If what I am doing is insecure, then sudo is insecure in even having the option not to reset the environment. But the fact is, it isn't if the security policy dictates that only trusted users will be using sudo -- in which case the functions are equally secure. You can't argue one w/o the other.
    – Astara
    Aug 5 '14 at 22:05

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.