Is there a way to prevent all commands from being defined as an alias?
For example a user shouldn't be able to define rm
or any other command (Ubuntu default commands) as an alias name.
There is no way you can prevent a user from defining whatever aliases they prefer. Consider:
/etc/bash.bashrc
. They enable it wherever they chose to./etc/bash.bashrc
, and all ~/.bashrc
and ~/.bash_aliases
via a script. They put their aliases in another file and source it.PROMPT_COMMAND
that disables certain aliases. They redefine or undefine PROMPT_COMMAND
.DEBUG
and undefine aliases. They remove the trap.unset
, builtin
and enable
; make alias
a function; declare -rf alias
to prevent users from modifying the function; and export the function. They run /bin/bash
with --rcfile
and --init-file
to start a new shell, where said builtins are now enabled.You could disable aliases at compile time, then it would be up to you to keep bash up-to-date and make sure you aren't affected by the next Shellshock. Of course, the users could build their own bash.
The only way to prevent a user from creating aliases is to provide them with a shell that doesn't support aliasing. This is generally an X/Y problem, where X is really a threat model that should be solved with appropriate controls or architectures rather than trying to solve the problem post-facto after a user is given a shell on a shared system.
Below, I provide a technically-correct answer, as well as some guidance on what problems this will and won't solve. I also provide some additional guidance on alternative controls.
You can use Bash's restricted shell by assigning rbash as the user's login shell. For example:
foo:x:2001:2001:restricted user:/home/foo:/bin/rbash
You must then disable the alias built-in for the user, preferably without breaking everyone else's shell too. As an example, you could add the following to a file such as /etc/profile.d/rbash.sh:
# Limit effect to users in a specific UID range.
if ((UID >= 2000)) && ((UID < 3000)); then
# Check shell options; disable alias builtins when shell is restricted.
if [[ $- =~ r ]]; then
enable -n alias
enable -n unalias
fi
fi
Unless you've placed the user into a chroot jail or provided them with a modified PATH that doesn't include access to other shells, there's nothing stopping the user from simply typing bash
at the prompt and getting an unrestricted shell.
In addition, by design the restricted shell prevents many common activities such as changing directories:
$ cd /tmp
rbash: cd: restricted
but doesn't prevent other scripts or programs in the PATH from doing so. This means you have to carefully craft the user's environment, and specifically that you need to prevent them from being able to modify the PATH in their startup files, because even though rbash makes PATH read-only it does so after initialization.
Even if you use rbash, you need to do so as part of a broader set of controls. Some examples may include:
Prevent non-technical users from accidentally invoking dangerous commands by providing default aliases such as rm -i
, mv -i
, and cp -i
in the /etc/bash.bashrc file.
enable -n alias
if you like.Traditional Unix permissions or POSIX ACLs to protect files and directories.
Logins that perform a single non-interactive command. For example:
foo:x:2001:2001:run foo.sh:/home/foo:/usr/local/bin/foo.sh
Use per-key SSH forced commands. For example:
# ~foo/.ssh/authorized_keys
command="/usr/local/bin/foo.sh" [remainder of line]
Use the OpenSSH ForceCommand option with a conditional Match block.
Use special tools like gitolite or scponly designed for your specific use case.
Use a chroot jail.
Use virtualization such as Xen, OpenVZ, LXC, VMware, VirtualBox, or other technologies to provide a segregated environment.
Once you have accurately defined your threat model, you can identify the most appropriate controls for your use case. Without a more meaningful understanding of why you want to prevent aliasing (e.g. what real-world problem does it solve?) you can't select the most appropriate controls.
This is quite a pointless endeavor, as muru's answer shows. But there are some options, but they are not perfect.
According to bash
manual, functions always take precedence over aliases, thus we could do the following:
xieerqi@eagle:~$ function alias { echo "Aliases are no-no" ; }
xieerqi@eagle:~$ alias TEST='rm'
Aliases are no-no
You could place function definition into the systemwide .bashrc
, however as muru pointed out, smart users will find way to get aliases by sourcing a different bashrc
file for example.
Another idea I've played with is enable
built-in.
alias
is a shell built in, and bash
has nice enable
command that allows enabling or disabling builtins. For instance, here's me disabling alias
.
xieerqi@eagle:~$ enable -n alias
xieerqi@eagle:~$ alias
No command 'alias' found, did you mean:
Command '0alias' from package 'zeroinstall-injector' (universe)
alias: command not found
xieerqi@eagle:~$ alias TEST='rm'
No command 'alias' found, did you mean:
Command '0alias' from package 'zeroinstall-injector' (universe)
alias: command not found
xieerqi@eagle:~$ enable alias
xieerqi@eagle:~$ alias
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
xieerqi@eagle:~$
Again, using systemwide bashrc
is an option here.
You could define (in /etc/profile
) a function called alias
which does the validation you want (probably using type -p
) (after all "Ubuntu default commands" are "executables in $PATH
") before calling the builtin alias
, BUT, as others have pointed out, your users could get around that. Why not get a different set of users, or educate them ("Defining an alias
that overrides a command is a Very Good Way of Shooting Oneself in the Foot, and causing confusion (e.g, Why does ls
prompt for my password?))?