I have a script that runs an utility every two days. This utility does some stuff on my system. It is a very known, widely used piece of open source software.

#!/usr/bin/env bash

#...do stuff here

Sometimes, but not always, utility will need me to enter my password so it can do its thing. I'm not watching utility run, and I'm not looking at any output either, 1>/dev/null. So I'd like for any attempt utility makes to sudo to automatically fail. Later I can run it manually and see what it needs superuser access for.

The problem is that it's not my script sudoing, it's utility. utility updates regularly so I don't want to edit it. Setting SUDO_ASKPASS to something useless looked promising but it requires sudo to have been caled with -A from utility. utility man page and online docs also don't have a way to "prevent sudo", neither did I have any luck googling "prevent system wide sudo."

I'm thinking of using this fake-sudo-test.bash:

#!/usr/bin/env bash

echo "echo 'no sudo for you $0' && exit 1" > $FAKE_SUDO
chmod u+x $FAKE_SUDO
sudo echo "I got superuser access"

This works because my $PATH has /usr/local/bin in front of /usr/bin.

Do you know a better way to do it?

PS: utility is brew, from the homebrew package manager for macOS, and I'm using brew upgrade in question. I thought making the question more generic would make it more useful.

$ sudo -V
Sudo version 1.8.17p1
    Sudoers policy plugin version 1.8.17p1
    Sudoers file grammar version 45
    Sudoers I/O plugin version 1.8.17p1
  • You could create a function named sudo that exits if called – Jesse_b Jul 4 '18 at 16:04
  • That's true. :) – Thomazella Jul 4 '18 at 16:40
  • @Jesse_b A shell function would not be callable from within the utility. – Kusalananda Jul 4 '18 at 16:45
  • brew practically never calls sudo (and if it does it calls /usr/bin/sudo so your false sudo won't work), maybe one of the formulae does? Anyway, can't you allow sudo brew in /etc/sudoers for the user in question? And then run the whole brew update with sudo? – nohillside Jul 4 '18 at 17:32
  • Are you sure it’s calling sudo? You could set the sudo prompt to something unique to confirm. – Jeff Schaller Jul 4 '18 at 17:37

It cannot ask for a password if it is not associated with a terminal:

setsid brew < /dev/null &> /dev/null

Or, if you want to capture its output:

setsid brew < /dev/null |& cat

That is, supposing you have setsid, which apparently may not be available on MacOS. If you want it and don't have it there are implementations available.

If you don't have sedsid but you have at:

[ -e ~/brew_$$.log ] && rm ~/brew_$$.log
at now << eof
brew > ~/brew_$$.lo_ 2>& 1 || true
mv ~/brew_$$.lo_ ~/brew_$$.log
while ! [ -e ~/brew_$$.log ]; do sleep 1; done
cat ~/brew_$$.log && rm ~/brew_$$.log

will run brew now-ish detached from the terminal, capture the output and copy it into the output stream of the script.

  1. Take yourself out of /etc/sudoers. This will make all sudo attempts fail.

    You may need to comment out this line:

    %sudo   ALL=(ALL:ALL) ALL

    Make sure you have an alternate way of gaining root (e.g. root password) so that you can undo this.

  2. Modify this line in /etc/sudoers:

    Defaults        env_reset


    Defaults        env_reset,timestamp_timeout=-1

    This makes sudo never ask for a password. (Source.)

  3. All failed sudo attempts are logged to /var/log/auth.log. Run utility, and look for a line like this in auth.log:

    Jul  4 12:23:07 host sudo: test_perm : user NOT in sudoers ; TTY=pts/1 ; PWD=/home/nick ; USER=root ; COMMAND=/bin/echo

    (This might be logged to somewhere else on macOS; I'm not sure.)

  • I think on my sudoers setting the timeout to -1 is making the timestamp never expire. I'll test it on linux and I think it'll work as we expect... I edited the post with sudo -V info. I still need to test taking myself out of the sudoers though. – Thomazella Jul 5 '18 at 14:42

On Linux, you can disable the effect of the setuid bit for the process and all other processes launched from it by enabling the no_new_privs flag (see prctl(2)). In shell scripts, you can do this with the setpriv utility from the util-linux package:

$ setpriv --no-new-privs sudo -v
sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?

So modifying your script to run setpriv --no-new-privs utility instead of utility should do the job, as long as you can live with the noisy error message above.

(Unfortunately, you mention brew, and this probably doesn’t work on macOS… but perhaps it still helps someone else.)

  • I didn't know about this, thanks, I'll try it. – Thomazella Jul 5 '18 at 17:17
  • As far as I can tell, setpriv doesn't seem to have an implementation for macOS. But yeah, nice you added it to the thread anyway. – Thomazella Jul 6 '18 at 6:08

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.