Restricted Shell (zsh)

### 4.3 Restricted Shell ¶

When the basename of the command used to invoke zsh starts with the letter ‘`r`’ or the ‘`-r`’ command line option is supplied at invocation, the shell becomes restricted. Emulation mode is determined after stripping the letter ‘`r`’ from the invocation name. The following are disabled in restricted mode:

- changing directories with the `cd` builtin
- changing or unsetting the `EGID`, `EUID`, `GID`, `HISTFILE`, `HISTSIZE`, `IFS`, `LD_AOUT_LIBRARY_PATH`, `LD_AOUT_PRELOAD`, `LD_LIBRARY_PATH`, `LD_PRELOAD`, `MODULE_PATH`, `module_path`, `PATH`, `path`, `SHELL`, `UID` and `USERNAME` parameters
- specifying command names containing `/`
- specifying command pathnames using `hash`
- redirecting output to files
- using the `exec` builtin command to replace the shell with another command
- using `jobs -Z` to overwrite the shell process’ argument and environment space
- using the `ARGV0` parameter to override `argv[0]` for external commands
- turning off restricted mode with `set +r` or `unsetopt RESTRICTED`

These restrictions are enforced after processing the startup files. The startup files should set up `PATH` to point to a directory of commands which can be safely invoked in the restricted environment. They may also add further restrictions by disabling selected builtins.

Restricted mode can also be activated any time by setting the `RESTRICTED` option. This immediately enables all the restrictions described above even if the shell still has not processed all startup files.

A shell Restricted Mode is an outdated way to restrict what users may do: modern systems have better, safer and more reliable ways to confine user actions, such as chroot jails, containers and zones.

A restricted shell is very difficult to implement safely. The feature may be removed in a future version of zsh.

It is important to realise that the restrictions only apply to the shell, not to the commands it runs (except for some shell builtins). While a restricted shell can only run the restricted list of commands accessible via the predefined ‘`PATH`’ variable, it does not prevent those commands from running any other command.

As an example, if ‘`env`’ is among the list of allowed commands, then it allows the user to run any command as ‘`env`’ is not a shell builtin command and can run arbitrary executables.

So when implementing a restricted shell framework it is important to be fully aware of what actions each of the allowed commands or features (which may be regarded as modules) can perform.

Many commands can have their behaviour affected by environment variables. Except for the few listed above, zsh does not restrict the setting of environment variables.

If a ‘`perl`’, ‘`python`’, ‘`bash`’, or other general purpose interpreted script is treated as a restricted command, the user can work around the restriction by setting specially crafted ‘`PERL5LIB`’, ‘`PYTHONPATH`’, ‘`BASHENV`’ (etc.) environment variables. On GNU systems, any command can be made to run arbitrary code when performing character set conversion (including zsh itself) by setting a ‘`GCONV_PATH`’ environment variable. Those are only a few examples.

Bear in mind that, contrary to some other shells, ‘`readonly`’ is not a security feature in zsh as it can be undone and so cannot be used to mitigate the above.

A restricted shell only works if the allowed commands are few and carefully written so as not to grant more access to users than intended. It is also important to restrict what zsh module the user may load as some of them, such as ‘`zsh/system`’, ‘`zsh/mapfile`’ and ‘`zsh/files`’, allow bypassing most of the restrictions.