Benjamin Sago / ogham / cairnrefinery / etc…

Technical notes Customise the ‘sudo’ prompt

Something that bothers me on the command-line is when I’m running a script that requires root access to install something (such as what Homebrew Cask does), so it runs sudo and prompts me for my password — only I have no idea which process I’m typing my password into.

All I see is this:

$ brew install --cask <thingy>
Downloading thingy... done
Installing thingy using sudo...
Password:

Sure, it’s possible to find out which process is running in the terminal and verify before you type your password in: you could examine the process tree and check that a sudo process is being run. Some terminals (including my favourite, iTerm2) offer a way to show the processes running in the current terminal session, making it even easier.

But the solution I arrived at is to customise the sudo prompt into something that I know what it looks like, and sudo knows what it looks like, but other programs do not. I also think this prompt looks better and is more usable, so it’s a triple win.

Prompt ‘Defaults’ directives

The file we are going to edit is /etc/sudoers.d/prompt, and we are going to use the visudo command to launch the editor to edit it. (For more on why we use this command, see the “Using ‘visudo’ to edit the configuration” section below.)

sudo visudo /etc/sudoers.d/prompt

I have it set the following two options, pwfeedback and passprompt, the latter of which takes an argument:

/etc/sudoers.d/prompt
Defaults pwfeedback
Defaults passprompt="[%u@%h] sudo %p -> %U: "

This customises the sudo prompt in two ways.

The first option, pwfeedback, shows a * character on the screen for each character I type of my password. I find that the visual feedback I get as I type each letter is well worth the slight security risk I now have of anybody being able to roughly tell how many letters I have in my password if they happen to be looking over my shoulder.

The second option, passprompt, adds more information to the prompt:

  • The %u@%h section expands to the name of the current user and the name of the current machine.
  • The %p section expands to the name of the user whose password I am being asked for. (This is almost guaranteed to be the same as the current user, but I include it all the same.)
  • The %U section expands to the name of the user the command will be run as. (This will usually be the root user.)
  • There’s an extra space at the end to make it look nicer.

After creating this file, make sure its permission bits are set to the same as the /etc/sudoers file — usually 0400 — so that non-root users cannot read it. This leaves you with a prompt that cannot be faked by another program, as it cannot discern the format without already being the root user.

The complete list of ‘%’-escape characters and their meanings is documented in the sudoers manual page, in the passprompt section.

With all this in place, here’s what I see when I use sudo:

$ brew install --cask <thingy>
Downloading thingy... done
Installing thingy using sudo...
[ben@mycomputer] sudo ben -> root: ******

Now I know for sure that I’m typing into a sudo prompt, and the prompt looks much nicer.

Using ANSI escape codes in the prompt

You may notice that missing from the list of escapes is any way to escape the escape character, which is needed for the ANSI escape codes used to add colours and styling to the text in the prompt.

If you want your prompt to be red — y’know, the internationally-recognised colour of ‘danger’ — you will have to literally insert the raw escape characters between the double quotes of the passprompt string, rather than escaping them. The way you do this depends on your editor. If you are using Vim, hitting Control-V and then Escape will insert the raw Escape character into your file.

Using ‘visudo’ to edit the configuration

Editing sudo’s configuration files can be dangerous. sudo fails safe, meaning that in the event of a syntax error or mistake in one of its configuration files, it will refuse to let anyone run anything through sudo. And if you’re relying on sudo itself to give you the privileges to edit its own configuration file, you’ll be left with no way to fix this.

The visudo command helps avoid this situation. It works by editing a temporary file instead of the real configuration file, and will only copy it into place after saving once it’s been checked for validity. Here it is in action:

$ sudo visudo /etc/sudoers.d/prompt
  (I deliberately insert a syntax error on line 3 and save the file.)
  /etc/sudoers.d/prompt:3:11: syntax error
  this line has a syntax error! aoeu aoeu !@#$%^&*()
            ^~~
  What now?  (I type ‘?’ to show the help.)
  Options are:
    (e)dit sudoers file again
    e(x)it without saving changes to sudoers file
    (Q)uit and save changes to sudoers file (DANGER!)

  What now?  (I type ‘x’ to leave my system intact.)

(If you are very worried, consider launching a root shell with sudo su before touching any of the sudo configuration and leaving it running in the background. It won’t be affected by any of the configuration changes until the session ends, and you can use it to repair your system if anything goes wrong.)