Quick Links

A restricted shell limits what a user account can do on Linux. A restricted user cannot change their directory, and you control which commands they have access to. Here's how to set up a restricted shell on Linux.

Restricted Shells

A restricted shell isn't a different shell. It's a different mode of a standard shell. The BashKornFish, and other shells can all be started in restricted shell mode. We'll be using Bash in this article, but the same principles apply to the other shells.

Because restricted shells are just another way of using your standard shell, they are easy to set up. There's nothing to install, and they're available wherever Linux is.

Restricted shells can be applied to scripts, too. That ensures that any damage they may cause if they've been written incorrectly is limited to the confines of their restricted world and that they don't have access to your entire computer.

Be aware, though, that restricted shells are not completely escape-proof. Someone with enough knowledge can escape a restricted shell. They're great for putting safe boundaries on a casual user, but don't rely on restricted shells for any real-world security on a production system.

Related: What's the Difference Between Bash, Zsh, and Other Linux Shells?

Restricted Bash

When you run Bash as a restricted shell, the user has some capabilities removed from them. Specifically, the user cannot:

  • Use
            cd
        
    to change the working directory.
  • Change the values of the $PATH ,
            $SHELL
        
    ,
            $BASH_ENV
        
    , or
            $ENV
        
    environmental variables (but they can read the current values).
  • Read or change
            $SHELLOPTS
        
    shell environmental options.
  • Redirect the output of a command.
  • Invoke commands that require a path to locate them. That is, you can't issue a command that has one or more forward slashes "/" in it.
  • Invoke
            exec
        
    to substitute a different process for the shell.
  • Use any of the restricted features in a script.

You can invoke a restricted Bash shell by using the -r (restricted) option. Trying to do a simple task like changing the working directory is forbidden. A terse message tells you that

        cd
    

is restricted.

bash -r

cd Documents

bash -r in a terminal window

The Bash shell can also detect when it has been invoked using "rbash" instead of "bash." This causes it to start as a restricted shell, too. This provides a convenient way to set the default shell for a particular user, which we'll use soon.

If we use the whereis command on Ubuntu to look for the rbash files, we'll see that the executable is in the "usr/bin" directory. The man page is in "/usr/share/man/man1" directory.

Using the ls command with the -l (long) option reveals that rbash is actually a symbolic link to bash .

whereis rbash

ls -l /usr/bin/rbash

whereis rbash in a terminal window

On Manjaro and Fedora, the rbash symbolic link had to be created. This works on both distributions:

whereis rbash

sudo ln -s /bin/bash /bin/rbash

whereis rbash

sudo ln -s /bin/bash /bin/rbash in a terminal window

The second time we use the whereis command, it finds rbash in the "/usr/bin" directory.

Restricting a User

Let's create a new user account named "Minnie." We'll set their shell to be the restricted shell using the -s (shell) option of the useradd command. We'll also set the account's password using thepasswd command, and we'll create a home folder for them.

The -p (parents) flag in the mkdir command tells mkdir to create the target directory and any parent directories that it needs to create, too. So by creating the "/home/minnie/bin" directory, we create the "/home/minnie" directory at the same time.

sudo useradd minnie -s /bin/rbash

sudo passwd minnie

sudo mkdir -p /home/minnie/bin

sudo useradd minnie -s /bin/rbash in a terminal window

When minnie logs in, she will be running in a restricted shell.

cd

cd in a terminal window

She cannot invoke commands that need to include a forward slash "/":

/usr/bin/ping

/usr/bin/ping in a terminal window

However, she can still execute commands that are found in the path.

ping

ping in a terminal window

That's not the behavior you might have expected, and it certainly isn't what we want. To tighten the restrictions further, we need to change the path that minnie's shell will use to look for commands.

Tightening the Restrictions

When we created minnie's home directory "/home/minnie", we also created a "/home/minnie/bin" directory. This is where that directory comes into play.

We're going to edit minnie's ".bash_profile" file and set her path to point to that directory only. We'll also restrict minnie's ".bash_profile" file so that only root can edit it. That means that no other user can edit that file and change her path.

sudo gedit /home/minnie/.bash_profile

sudo gedit /home/minnie/.bash_profile in a terminal window

Either edit the existing "PATH=" or add the following line:

PATH=$HOME/bin

PATH=$HOME/bin in a terminal window

Save the file. We'll change the owner of the file to root using the chown command and change the file permissions using the chmod command. Only the root user will be able to edit the file.

sudo chown root:root /home/minnie/.bash_profile

sudo chmod 755 /home/minnie/.bash_profile

ls -l /home/minnie/.bash_profile

sudo chown root:root /home/minnie/.bash_profile in a terminal window

The next time user minnie logs in, her path points to a single folder.

echo $PATH in a terminal window

Our restricted user minnie can only use Bash built-in commands like echo, alias, and logout. She can't even use ls!

ls

ls in a terminal window

We'll need to slacken our stranglehold a little if we want them to be able to do anything useful at all. We'll create some symbolic links from minnie's "bin" directory to the commands that we want minnie to be able to use.

sudo ln -s /bin/ls /home/minnie/bin

sudo ln -s /bin/top /home/minnie/bin

sudo ln -s /bin/uptime /home/minnie/bin

sudo ln -s /bin/pinky /home/minnie/bin

sudo ln -s /bin/ls /home/minnie/bin in a terminal window

When minnie next logs in, she'll find that she can use the Bash built-in commands, plus those commands that have been linked to.

ls

pinky dave

uptime

ls in a terminal window

Restricting Existing Users

We created minnie as a new user. To change the shell of an existing user, we can use the -s (shell) option of the usermod command.

sudo usermod -s /bin/rbash mary

sudo usermod -s /bin/rbash mary in a terminal window

You can use the less command on the "/etc/passwd" file to quickly see what shell is set as a user's default shell.

less /etc/passwd

less /etc/passwd in a terminal window

We can see that user mary will use the restricted shell when she next logs in.

Output of less /etc/passwd in a terminal window

Remember to apply the other changes to restricts their $PATH environment variable and to set the commands you want the user mary to be able to execute.

Restricting Scripts

A regular, unrestricted user can launch scripts that are executed in a restricted shell. Copy the following lines and paste them into an editor. Save the file as "restricted.sh" and close the editor.

#!/bin/bash
    

# script starts in normal Bash shell

echo "## In UNrestricted mode! ##"

echo

echo "Current directory: `pwd`"

echo "Changing directory"

cd /usr/share

echo "Now in directory: `pwd`"

echo "Changing to home directory"

cd ~

echo "Now in directory: `pwd`"

# Setting restricted mode

set -r

echo

echo "## In restricted mode! ##"

echo

echo "Current directory: `pwd`"

echo "Changing directory to /home/"

cd /home

echo "Still in directory: `pwd`"

echo

echo "Trying to start another shell"

/bin/bash

echo

echo "Trying to redirect command output"

ls -l $HOME > my_files.txt

cat my_files.txt

echo

exit 0

We need to use the chmod command with the +x (execute) flag to make the script executable.

chmod +x restricted.sh

chmod +x restricted.sh in a terminal window

The first part of the script runs in a normal shell.

./restricted.sh

./restricted.sh in a terminal window

The second portion of the script---the bit after the "set -r" line---runs in a restricted shell.

output from /restricted.sh in a terminal window

None of the attempted actions succeed in the restricted portion of the script.

An entire script can be made to run in a restricted shell by adding -r to the first line:

!#/bin/bash -r

Remember Houdini

Restricted shells are useful, but not completely infallible. A sufficiently skilled user may be able to escape them. But when used judiciously, they are a useful way to establish a set of limitations for a particular account.