Restricted Shell (rbash) in Bash: Using Limited Environments Correctly
AI generated
$_
#!/
Bash · Security · Restricted Shell · SSH
Restricted Shell (rbash) in Bash
Using limited environments correctly, without a false sense of security

The restricted shell rbash blocks cd, PATH changes, and calling programs through a path containing a slash. That is enough for simple, benign restrictions like an SFTP replacement, but it can be bypassed with documented techniques relatively easily. Anyone using rbash should know exactly what it covers and what needs additional hardening.

15 min read rbash · bash -r · SSH ForceCommand Bash 4.x · 5.x · Linux

1. What a restricted shell is and what it is meant for

A restricted shell is a Bash variant that blocks a fixed set of actions before any command even runs. It is activated either through the symlink or command name rbash, the startup flag bash -r, or by setting the restricted option at runtime with set -r. All three paths lead to the same restricted mode, only the timing of activation differs.

The purpose of a restricted shell is not to replace a full sandbox system, but to prevent benign misuse and to limit a user's range of action within a clearly defined, usually already trusted context. Typical use cases are a limited login for an external contractor who should only run one fixed script, or an SFTP-like access where the user should not move freely through the filesystem.

2. What exactly gets restricted: cd, PATH, programs with a slash

In an rbash session, the following actions are specifically forbidden: changing directory with cd, changing the variables PATH, SHELL, ENV, or BASH_ENV, running commands whose name contains a slash (such as /bin/bash or ./script.sh), and redirecting output into a new file with >, >>, or >|. Even turning off restricted mode itself via set +r is blocked once it is active.

This list already shows the underlying principle: rbash does not forbid specific commands directly, it restricts the ways a user can invoke programs outside a predefined PATH and manipulate files outside allowed directories. Programs located inside the allowed PATH keep running perfectly normally, which is why the contents of that directory form the actual security boundary, not the shell itself.


# Minimal rbash setup for a restricted account
useradd -m -s /bin/rbash deploy-partner
mkdir -p /home/deploy-partner/bin
ln -s /usr/bin/rsync /home/deploy-partner/bin/rsync

# Only this directory is exposed via PATH, set in the user's profile
echo 'PATH=$HOME/bin' >> /home/deploy-partner/.bash_profile
echo 'export PATH' >> /home/deploy-partner/.bash_profile
chmod 555 /home/deploy-partner/bin  # not writable by the user

3. Typical use case: limited SSH access for contractors

A common scenario is an external contractor who should only run a specific deployment script over SSH, without getting free shell access to the server. Combined with the SSH option ForceCommand in sshd_config, or directly in the authorized_keys file via command="...", the login can be limited to exactly one command, while rbash additionally prevents that command from loading arbitrary other programs internally.

The order of these defenses matters: ForceCommand decides what runs at all upon login, and rbash then restricts what that command itself is still allowed to do if it becomes interactive or opens a subshell. Both mechanisms together are considerably more robust than either alone, because ForceCommand prevents a direct shell login from the start and rbash additionally limits the range of action inside the allowed command.


# In /home/deploy-partner/.ssh/authorized_keys
command="/home/deploy-partner/bin/deploy.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAA... partner@example.com

# In sshd_config, alternative per-user ForceCommand
Match User deploy-partner
    ForceCommand /home/deploy-partner/bin/deploy.sh
    ChrootDirectory /home/deploy-partner

4. Setting up an rbash environment correctly

The most important step during setup is pointing PATH to a single directory, not writable by the user, containing only vetted programs, and setting that PATH in a profile file the user can no longer modify. If PATH is instead set interactively or in a file the user can write to, they can simply overwrite it on the next login before rbash even applies.

In addition, every script inside the exposed directory should be written defensively: no calling external programs with user-controlled arguments, no eval calls on user input, and where possible, avoiding shell interpreters in favor of statically compiled wrapper programs. rbash restricts the shell itself, but it does not control what the exposed programs do internally with their own arguments.

5. Known escape techniques: why rbash alone is not enough

rbash has been known for years for a whole range of documented escape routes. Programs that can start an interactive shell themselves, such as vi with :!bash, less with !bash, or ftp, scp, and similar tools with built-in shell escapes, completely defeat the restricted shell as soon as they sit inside the exposed PATH. Options like ssh -o ProxyCommand=..., or redirecting script execution via source, can also break out of the restriction in certain configurations.

Another known route is that rbash only forbids the user from directly running a program via a slash path, but an already-allowed program in PATH can still open its own path containing a slash internally, for example an editor that reads or writes arbitrary paths through its own file-open feature. That is exactly why the ground rule is: only expose programs proven to offer no shell escapes, no filesystem navigation, and no subprocess calls with free-form arguments.

6. Hardening rbash sensibly: additional layers instead of relying on one

Because rbash alone is not a hard security boundary, it belongs in a layered concept: a chroot environment or a Linux namespace additionally limits which files are even visible, regardless of whether an escape from rbash succeeds. On systems running systemd, services can be further hardened with NoNewPrivileges, ProtectSystem, and similar sandbox directives that stay effective even after a successful rbash escape.

For SSH access, it is also recommended to place the user in a dedicated group without sudo rights, set the home directory restrictively (chmod 750), and regularly audit which binaries actually live in the exposed PATH. An rbash setup that never gets reviewed tends to accumulate extra, accidentally exposed programs over time, which opens new escape routes.


# Combine rbash with a minimal chroot for an SFTP-only user
usermod -d /home/partner -s /bin/rbash partner

# In sshd_config: chroot plus internal-sftp, no rbash escape possible
# because there is no shell at all inside the jail
Match User partner
    ChrootDirectory /home/partner
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no

7. When a real alternative to rbash is the better choice

For pure file transfer, OpenSSH's internal-sftp combined with ChrootDirectory is almost always the more robust solution, because it never starts a shell at all, which eliminates the entire class of rbash escapes from the start. For a single, clearly defined command, a plain ForceCommand without rbash is often sufficient, as long as the command itself does not offer an interactive subshell.

For more strongly isolated environments, containers with a minimal root filesystem or dedicated jump hosts with strict audit logging are the noticeably more robust choice compared to any form of restricted shell, because they isolate at the kernel level rather than the application level. rbash remains a useful, lightweight building block, but not the sole line of defense for security-critical access.

8. Common mistakes when operating rbash environments

A frequent operational mistake is leaving an interactive login script like .bashrc or .bash_profile writable for the restricted user. Since rbash forbids changing PATH at runtime but not editing the profile file itself, a user with write access to their own home directory can freely extend PATH on the next login and effectively lift the restriction.

A second common mistake is placing an overly powerful program inside the exposed PATH, such as a generic text editor or an archiving tool with a built-in shell feature, without first carefully checking its full feature set. Every additional program in a restricted shell's PATH enlarges the attack surface, which is why the list of allowed programs should be kept as small as possible.

9. rbash compared to other isolation mechanisms

rbash differs from chroot, containers, and namespaces mainly in the attack vector it protects against: rbash controls which shell features may be used, while chroot and containers control which files and resources are even visible in the first place. Both layers complement each other but do not replace one another, which is why production setups usually combine several of these mechanisms.

The table below places rbash alongside the most common alternatives and shows which mechanism fits which level of required isolation, from simple misuse prevention up to complete process isolation.

Mechanism Isolation level Protection against escapes Typical use
rbash Shell features (cd, PATH, redirect) Weak, documented escapes exist Misuse prevention, simple SSH access
internal-sftp + chroot Filesystem, no shell Very strong, no shell present Pure file transfer without commands
ForceCommand Allowed command at login Medium, depends on the command Running exactly one fixed script
Linux namespace/container Kernel resources (PID, network, filesystem) Strong, kernel-enforced Fully isolated environments
systemd sandboxing Process capabilities, file access Strong, complements other layers Services with reduced privileges

Mironsoft

Shell automation, DevOps tooling and deployment infrastructure

Shell scripts that hold up in production?

We review existing Bash scripts, spot fragile patterns and replace them with robust Bash patterns: complete error handling, logging and safe parallelization for your deployment stack.

Code Review

ShellCheck analysis and manual review for critical Bash pattern violations.

Refactoring

Retrofitting error handling, logging and safe file operations.

CI Integration

Wiring ShellCheck and BATS into pipelines and building regression tests.

10. Summary

Restricted Shell (rbash): The Essentials at a Glance

Activation

bash -r, the rbash command, or set -r at runtime all put the shell into restricted mode with the same limitations.

Restrictions

Changing cd, PATH/SHELL/ENV, running programs with a slash in the name, and redirecting output into new files are all blocked.

Escapes

Programs with a built-in shell feature like vi, less, or scp defeat rbash as soon as they sit inside the exposed PATH.

Recommendation

Combine rbash with chroot, ForceCommand, and regular PATH audits, never use it as the sole security boundary.

11. FAQ: Restricted Shell (rbash): The Essentials at a Glance

1How do I activate rbash for a user?
Either set the user's login shell to /bin/rbash, start a script with bash -r, or run set -r inside a script. All three activate the same restricted mode.
2Can a user change directory under rbash?
No, cd is blocked entirely. The user stays in the directory where the session started, usually the configured home directory.
3Why can a user still run arbitrary programs despite rbash?
The exposed PATH likely contains a program with a built-in shell feature, such as an editor or a transfer tool with an escape command.
4Is rbash suitable as a production security boundary?
Not on its own. rbash should always be combined with chroot, ForceCommand, or container isolation, since documented escape techniques exist.
5What is the difference between rbash and internal-sftp?
internal-sftp never starts a shell at all and is therefore more robust for pure file transfer. rbash starts a real, just limited, shell and fits cases where commands actually need to run.
6Can a user turn off restricted mode themselves?
set +r is blocked inside an active restricted session. The user cannot lift the mode themselves at runtime.
7How do I protect PATH from manipulation by the user?
Set PATH in a profile file not owned by, and not writable by, the user, for example root-owned with chmod 555 on the target directory.
8Does rbash also work for interactive sessions without SSH?
Yes, rbash can be set for any login shell, regardless of the access method. The most common use case, though, is indeed SSH with ForceCommand.
9What happens if an exposed program opens a path with a slash itself?
rbash only forbids the user from directly starting a program via a slash path, not the internal opening of files by an already-running, allowed program.
10Should I combine rbash with chroot?
Yes, that is the recommended combination. chroot restricts visible files at the kernel level, regardless of whether a user manages to escape rbash itself.