SSD Nodes Learn 🎉 VPS from $5.50/mo
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-13

Ubuntu sudo-rs: Which sudoers Rules Go Break?

Ubuntu 26.04 now uses sudo-rs by default. Wildcards inside command arguments no longer match, so see the sudoers rules to replace and why 24.04 differs.

Ubuntu 26.04 LTS dey change for sudo-rs

Ubuntu 26.04 LTS dey ship sudo-rs as the default sudo, so the sudo command for fresh server go run the Rust reimplementation instead of the original C program. Most sudoers files go still work exactly as dem dey work before. The rule wey go break na the one wey get wildcard inside command arguments, because sudo-rs no dey match glob patterns against argument text.

Ubuntu 25.10 na the first release wey make this change, and 26.04 LTS keep am. Ubuntu 24.04 LTS no dey affected, because e still dey select the original sudo unless you install sudo-rs by hand. This matter go start when you upgrade from Ubuntu 24.04 go 26.04, or when you build new box for the newer release. If you dey run the interim releases too, how LTS and interim Ubuntu releases different for server explain which machine go meet change like this first.

Check which sudo your server dey actually run

No use release number take work this one out. Ask the machine.

sudo --version
update-alternatives --config sudo
dpkg -l 'sudo*'

Trust sudo --version for your own box pass any version table for internet, including this page. update-alternatives --config sudo na the other half of the answer: e list every installed provider of /usr/bin/sudo and mark the one wey dem select. Say package dey installed no mean say dem select am, so read the selection, no be package list.

Dem package both implementations during the transition. The Rust one na sudo-rs, for version 0.2.13 for 26.04 as of August 2026. The original one, wey Todd C. Miller maintain, dem package am as sudo.ws, and e programs get .ws suffix: sudo.ws and visudo.ws.

Why Ubuntu switch go sudo-rs

sudo na setuid root. Any user for the box fit start am, and e dey start with full privileges, so memory bug inside am na local root exploit. CVE-2021-3156 na exactly that: heap buffer overflow wey any local user fit reach, and e dey inside released code for about ten years. Rust dey catch that kind bug for compile time, and na the main reason for the rewrite.

The second reason na scope, and na this one dey affect your config. The original sudo don collect plenty features for three decades, and every feature mean more code wey dey run as root. sudo-rs implement subset on purpose. Anything wey the authors judge as niche or actively harmful, dem leave am out. So sudoers construct wey work for years fit simply no dey there. Your wildcard rule na one of dem.

Memory safety remove one class of bug. E no make program bug free, and sudo-rs don release security fixes for itself since e become the default. Patch am like any other software.

Which sudoers rules still dey work

Na the same file. sudo-rs dey read /etc/sudoers and the drop-in files for /etc/sudoers.d/. The ordinary rules wey server operator dey write still dey supported:

  • deploy ALL=(ALL:ALL) ALL, plus group forms like %sudo ALL=(ALL:ALL) ALL
  • the NOPASSWD: and PASSWD: tags
  • User_Alias, Runas_Alias, Host_Alias and Cmnd_Alias
  • command wey get exact argument list, for example /usr/bin/systemctl restart app-api
  • command wey "" follow, wey allow the command only when e get no argument
  • command wey * follow as the final argument, wey allow any extra arguments
  • directory path wey end for /, wey allow any command inside that directory
  • ! to remove one command from a list
  • useful subset of Defaults, including secure_path, env_keep, env_check, timestamp_timeout, passwd_tries, editor, umask, targetpw, rootpw and use_pty

Two defaults dey behave differently, and dem dey catch people. You no fit turn off env_reset for sudo-rs; e dey always on. use_pty dey on by default, so the command go run for its own pseudo-terminal.

Wetin make your wildcard sudoers rule stop matching

Wildcards still dey allowed for one place: the command file name. A rule of %ops ALL = /sbin/fsck* still permits sudo fsck and sudo fsck_exfat, because * dey part of the path wey dey match against the filesystem.

Inside the argument list, sudo-rs accepts only two special forms, and none of dem be pattern. "" mean say no argument dey allowed. A final * mean any remaining arguments. Every other argument dey compare as literal text. So %ops ALL = /sbin/service ntp * dey okay, because ntp na literal and * dey last. But rule like this one no grant the thing wey you intend:

deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*

app-* na pattern for middle of an argument. sudo-rs no expand am, so the rule no cover systemctl restart app-api and sudo go refuse the command. Two commands fit show you the real state of any rule for your own server: sudo -l -U deploy, wey you run as root, go print wetin that account fit actually run, while sudo visudo -c go tell you whether the file parse at all. Run dem before you start editing anyhow.

Wildcard rule dey always be loophole

For the original sudo, dem join the arguments wey you type into one string, then dem match am against the rule argument string with a glob. Glob dey match whitespace. Na this part almost everybody dey miss.

sudo-rs documentation give the clearest demonstration. Rule of /bin/rm *.txt also allow sudo rm -rf /home .txt, because the one * swallow -rf /home and the joined string still end with .txt. The rule read as "only text files". But e mean "any arguments at all, as long as the line end in .txt".

The same thing apply to the systemctl example. Because dem compare the arguments as one joined string, trailing pattern also match anything wey you append after am. So restart app-* cover restart app-api plus any extra arguments wey the caller add. Pattern inside one argument give away the arguments around am, and na for arguments command power dey. sudo-rs reject the construct instead of trying to make am safe, because no general safe form of am dey.

Wildcard badala ka explicit command list

Plenty wildcard rules dey exist because person no wan type four lines. Type the four lines.

Cmnd_Alias APP_RESTART = /usr/bin/systemctl restart app-api, /usr/bin/systemctl restart app-worker
Cmnd_Alias APP_STATUS = /usr/bin/systemctl status app-api, /usr/bin/systemctl status app-worker
deploy ALL=(root) NOPASSWD: APP_RESTART, APP_STATUS

Make sure say path correct. Rule wey name /bin/systemctl for system where binary dey for /usr/bin/systemctl no go ever match, and the failure go look exactly like permissions problem. Confirm am with command -v systemctl and paste wetin e print.

Put the rule for im own drop-in file instead of /etc/sudoers, so package upgrade no go ever clash with your edit:

sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deploy

Name the file without dot and without trailing tilde. Original sudo dey ignore files for sudoers.d wey im names contain dot, so 90-deploy.conf na common silent no-op. Following this convention no cost anything.

Use root-owned wrapper when the list don too long

When the allowed set too large to list, move the decision comot sudoers put am inside one small program wey root own.

sudo tee /usr/local/sbin/app-restart >/dev/null <<'EOF'
#!/bin/sh
set -eu
case "${1:-}" in
  app-api|app-worker) ;;
  *) echo "app-restart: not allowed: ${1:-}" >&2; exit 1 ;;
esac
exec /usr/bin/systemctl restart "$1"
EOF
sudo chown root:root /usr/local/sbin/app-restart
sudo chmod 0755 /usr/local/sbin/app-restart
ls -l /usr/local/sbin/app-restart

The sudoers side go then name only one command:

deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart *

The trailing * dey acceptable here because na the script, no be sudo, decide wetin dem allow. This one go hold only while root own the script and nobody else fit write to am. If deploy fit write to the file, deploy fit replace wetin dey inside and run anything as root. This one worse pass the wildcard rule wey you remove. Check the mode with ls -l. If the output no clear to you, learning the drwxr-xr-x permission string fit take only five minutes. The same rule apply to the directory too: /usr/local/sbin no suppose writable by the account, because writable directory mean say dem fit replace the whole file.

Give the job im own account instead of a sudo rule

The better question plenty times na why the command need root at all. Service wey run with im own user fit be managed by that user, and no sudoers line go dey involved. For system units, systemd don already hand over that decision to polkit, so rule fit name one unit and one operator:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        action.lookup("unit") == "app-api.service" &&
        subject.user == "deploy") {
        return polkit.Result.YES;
    }
});

Save am as /etc/polkit-1/rules.d/50-app-api.rules and deploy fit run systemctl restart app-api without any sudo. Test am from the exact context wey go use am, because rule wey work for your SSH session still need confirmation from cron before you rely on am. Anyhow, the account wey dey do the work suppose exist only for that work, and na the same reason behind least-privilege user accounts for VPS.

Wetin sudo-rs no include

sudo -E no dey implemented. Use Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" name the variables wey you need instead, and remember say env_reset dey always on, so anything wey no keep go clear.

Central sudoers storage for LDAP don comot. sudoers.ldap and cvtsudoers no dey implemented, and dem remove sudo-ldap package for 26.04. LDAP authentication through PAM or SSSD still dey work. Na the policy-in-a-directory part wey no dey included.

INTERCEPT, wey try stop shell escapes from command wey permission allow, no dey implemented. E no ever work against determined user anyway. If rule allow person run editor or interpreter as root, dem get root access, and no sudo option fit change that.

Session recording no dey implemented, so no I/O log and no sudoreplay dey. Logging dey go syslog only, and no logfile option dey to redirect am go another place. So sudo messages go land wherever your system already dey send syslog.

Make you switch go back to sudo.ws?

You fit, and during the 26.04 cycle dem go still package the original for exactly this reason.

sudo apt install sudo.ws
update-alternatives --config sudo
sudo update-alternatives --set sudo /usr/bin/sudo.ws

Copy the exact paths from the --config output, no be from this page, because na the list wey your own system go accept. If you later wan go back to sudo-rs, set the alternative to the sudo-rs binary path from that same list.

Keep one second SSH session open, logged in, and idle before you touch anything wey affect sudo. If sudoers file no parse, or an alternative point to binary wey no dey installed, you fit lose every way to become root for remote box. Make this habit join everything else wey you dey do for the first ten minutes for new VPS.

Treat the switch back as deadline, no be fix. E go give you one week to rewrite the rules properly. The rewrite still worth doing by itself, because every wildcard rule wey you delete bin dey grant more access than the author understand.

FAQ

My sudoers wildcard rule for Ubuntu 26.04 why stop working?

Ubuntu 26.04 LTS dey select sudo-rs as the default sudo, and sudo-rs no dey match wildcard patterns inside command arguments. E allow wildcard for command file name, "" to mean say no arguments dey, and one * as the final argument. Rule like /usr/bin/systemctl restart app-* put pattern for middle of argument, so e no grant any permission and command go dey refused. Run sudo -l -U deploy as root to see wetin the account really get, then replace the rule with exact commands or root-owned wrapper script.

How I fit switch back to the original sudo for Ubuntu 26.04?

The original package name na sudo.ws. Install am with sudo apt install sudo.ws, then point the alternative to am with sudo update-alternatives --set sudo /usr/bin/sudo.ws. Run update-alternatives --config sudo first to read the exact paths wey your system dey offer, and keep another SSH session open while you change am. This no go bring back sudo-ldap, because dem remove am from 26.04 no matter which implementation you select.

sudo-rs dey read the same /etc/sudoers file?

Yes. sudo-rs dey read /etc/sudoers and the drop-in files under /etc/sudoers.d/, with the same syntax for users, groups, aliases, run-as specifications, and the NOPASSWD tag. E implement only part of the sudoers language, so the differences show as constructs wey no dey available, instead of constructs wey dey behave differently. Edit with sudo visudo, then verify with sudo visudo -c before you close your session.

Wetin replace sudo -E for sudo-rs?

sudo -E no dey implemented, and dem don already discourage am for the original sudo, because giving root process an environment wey caller controls na known way to change how that process behaves. Name the variables wey you really need inside sudoers instead, with line like Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". env_reset dey always on for sudo-rs and you no fit disable am, so every variable wey you no keep go clear.

#sudo#sudo-rs#ubuntu#sudoers#permissions