Limitations of the '!' operator
     It is generally not effective to 'subtract' commands from ALL using
     the '!' operator.  A user can trivially circumvent this by copying
     the desired command to a different name and then executing that.
     For example:
     bill    ALL = ALL, !SU, !SHELLS
     Doesn't really prevent bill from running the commands listed in SU
     or SHELLS since he can simply copy those commands to a different
     name, or use a shell escape from an editor or other program.
     Therefore, these kind of restrictions should be considered advisory
     at best (and reinforced by policy).
     In general, if a user has sudo ALL there is nothing to prevent them
     from creating their own program that gives them a root shell (or
     making their own copy of a shell) regardless of any '!' elements in
     the user specification.
   Security implications of fast_glob
     If the fast_glob option is in use, it is not possible to reliably
     negate commands where the path name includes globbing (aka
     wildcard) characters.  This is because the C library's fnmatch(3)
     function cannot resolve relative paths.  While this is typically
     only an inconvenience for rules that grant privileges, it can
     result in a security issue for rules that subtract or revoke
     privileges.
     For example, given the following sudoers file entry:
     john    ALL = /usr/bin/passwd [a-zA-Z0-9]*, /usr/bin/chsh [a-zA-Z0-9]*,\
                   /usr/bin/chfn [a-zA-Z0-9]*, !/usr/bin/* root
     User john can still run /usr/bin/passwd root if fast_glob is
     enabled by changing to /usr/bin and running ./passwd root instead.
   Preventing shell escapes
     Once sudo executes a program, that program is free to do whatever
     it pleases, including run other programs.  This can be a security
     issue since it is not uncommon for a program to allow shell
     escapes, which lets a user bypass sudo's access control and
     logging.  Common programs that permit shell escapes include shells
     (obviously), editors, paginators, mail and terminal programs.
     There are four basic approaches to this problem:
     restrict  Avoid giving users access to commands that allow the user
               to run arbitrary commands.  Many editors have a
               restricted mode where shell escapes are disabled, though
               sudoedit is a better solution to running editors via
               sudo.  Due to the large number of programs that offer
               shell escapes, restricting users to the set of programs
               that do not is often unworkable.
     intercept
               Many systems that support shared libraries have the
               ability to override default library functions by pointing
               an environment variable (usually LD_PRELOAD) to an
               alternate shared library.  On such systems, sudo's
               intercept functionality can be used to transparently
               intercept an attempt to run a new command, allow or deny
               it based on sudoers rules, and log the result.  For
               example, this can be used to restrict the commands run
               from within a privileged shell.  Note, however, that this
               applies only to dynamically-linked executables.
               Statically-linked executables and executables running
               under binary emulation are not affected.  Also, most
               shells support built-in commands and the ability to read
               or write sensitive files that cannot be intercepted by
               sudo.
               Currently, sudo's intercept functionality only works for
               programs that use the execve() system call to run the new
               command.  This may be expanded in a future release of
               sudo.  Because most dynamic loaders ignore LD_PRELOAD (or
               the equivalent) when running set-user-ID and set-group-ID
               programs, sudoers will not permit such programs to be run
               in intercept mode.
               The intercept feature is known to work on Solaris, *BSD,
               Linux, macOS, HP-UX 11.x and AIX 5.3 and above.  It
               should be supported on most operating systems that
               support the LD_PRELOAD environment variable.  Check your
               operating system's manual pages for the dynamic linker
               (usually ld.so, ld.so.1, dyld, dld.sl, rld, or loader) to
               see if LD_PRELOAD is supported.
               To enable intercept mode on a per-command basis, use the
               INTERCEPT tag as documented in the User Specification
               section above.  Here is that example again:
               chuck   research = INTERCEPT: ALL
               This allows user chuck to run any command on the machine
               'research' in intercept mode.  Any commands run via shell
               escapes will be validated and logged by sudo.  If you are
               unsure whether or not your system is capable of
               supporting intercept, you can always just try it out and
               check whether or not external commands run via a shell
               are logged when intercept is enabled.
     log       There are two separate but related ways to log additional
               commands.  The first is to enable I/O logging using the
               log_output flag.  This will log the command's output but
               will not create an event log entry when the additional
               command is run.  The second is to enable the log_children
               flag in sudoers which will create an event log entry
               every time a new command is run.  If I/O logging is also
               enabled, the log entry will include a time offset into
               the I/O log to indicate when the command was run.  This
               offset can be passed to the sudoreplay(8) utility to
               replay the I/O log at the exact moment when the command
               was run.  The log_children flag uses the same mechanism
               as intercept (see above) and has the same limitations.
     noexec    sudo's noexec functionality can be used to prevent a
               program run by sudo from executing any other programs.
               On most systems, it uses the same mechanism as intercept
               (see above) and thus the same caveats apply.  The noexec
               functionality is capable of blocking execution of
               commands run via the execl(), execle(), execlp(),
               exect(), execv(), execve(), execveat(), execvP(),
               execvp(), execvpe(), fexecve(), popen(), posix_spawn(),
               posix_spawnp(), system(), and wordexp() functions.  On
               Linux, a seccomp() filter is used to implement noexec.
               On Solaris 10 and higher, noexec uses Solaris privileges
               instead of the LD_PRELOAD environment variable.
               To enable noexec for a command, use the NOEXEC tag as
               documented in the User Specification section above.  Here
               is that example again:
               aaron   shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
               This allows user aaron to run /usr/bin/more and
               /usr/bin/vi with noexec enabled.  This will prevent those
               two commands from executing other commands (such as a
               shell).  If you are unsure whether or not your system is
               capable of supporting noexec you can always just try it
               out and check whether shell escapes work when noexec is
               enabled.
     Note that restricting shell escapes is not a panacea.  Programs
     running as root are still capable of many potentially hazardous
     operations (such as changing or overwriting files) that could lead
     to unintended privilege escalation.  In the specific case of an
     editor, a safer approach is to give the user permission to run
     sudoedit (see below).
   Secure editing
     The sudoers plugin includes sudoedit support which allows users to
     securely edit files with the editor of their choice.  As sudoedit
     is a built-in command, it must be specified in the sudoers file
     without a leading path.  However, it may take command line
     arguments just as a normal command does.  Wildcards used in
     sudoedit command line arguments are expected to be path names, so a
     forward slash ('/') will not be matched by a wildcard.
     Unlike other sudo commands, the editor is run with the permissions
     of the invoking user and with the environment unmodified.  More
     information may be found in the description of the -e option in
     sudo(8).
     For example, to allow user operator to edit the 'message of the
     day' file:
           operator        sudoedit /etc/motd
     The operator user then runs sudoedit as follows:
           $ sudoedit /etc/motd
     The editor will run as the operator user, not root, on a temporary
     copy of /etc/motd.  After the file has been edited, /etc/motd will
     be updated with the contents of the temporary copy.
     Users should never be granted sudoedit permission to edit a file
     that resides in a directory the user has write access to, either
     directly or via a wildcard.  If the user has write access to the
     directory it is possible to replace the legitimate file with a link
     to another file, allowing the editing of arbitrary files.  To
     prevent this, starting with version 1.8.16, symbolic links will not
     be followed in writable directories and sudoedit will refuse to
     edit a file located in a writable directory unless the
     sudoedit_checkdir option has been disabled or the invoking user is
     root.  Additionally, in version 1.8.15 and higher, sudoedit will
     refuse to open a symbolic link unless either the sudoedit_follow
     option is enabled or the sudoedit command is prefixed with the
     FOLLOW tag in the sudoers file.
   Time stamp file checks
     sudoers will check the ownership of its time stamp directory
     (/run/sudo/ts by default) and ignore the directory's contents if it
     is not owned by root or if it is writable by a user other than
     root.  Older versions of sudo stored time stamp files in /tmp; this
     is no longer recommended as it may be possible for a user to create
     the time stamp themselves on systems that allow unprivileged users
     to change the ownership of files they create.
     While the time stamp directory should be cleared at reboot time,
     not all systems contain a /run or /var/run directory.  To avoid
     potential problems, sudoers will ignore time stamp files that date
     from before the machine booted on systems where the boot time is
     available.
     Some systems with graphical desktop environments allow unprivileged
     users to change the system clock.  Since sudoers relies on the
     system clock for time stamp validation, it may be possible on such
     systems for a user to run sudo for longer than timestamp_timeout by
     setting the clock back.  To combat this, sudoers uses a monotonic
     clock (which never moves backwards) for its time stamps if the
     system supports it.
     sudoers will not honor time stamps set far in the future.  Time
     stamps with a date greater than current_time + 2 * TIMEOUT will be
     ignored and sudoers will log and complain.
     If the timestamp_type option is set to 'tty', the time stamp record
     includes the device number of the terminal the user authenticated
     with.  This provides per-terminal granularity but time stamp
     records may still outlive the user's session.
     Unless the timestamp_type option is set to 'global', the time stamp
     record also includes the session ID of the process that last
     authenticated.  This prevents processes in different terminal
     sessions from using the same time stamp record.  On systems where a
     process's start time can be queried, the start time of the session
     leader is recorded in the time stamp record.  If no terminal is
     present or the timestamp_type option is set to 'ppid', the start
     time of the parent process is used instead.  In most cases this
     will prevent a time stamp record from being re-used without the
     user entering a password when logging out and back in again.