Ubuntu 26.04 sudo-rs: wetin change for sudoers
Ubuntu 26.04 and 25.10 dey use sudo-rs by default. Wildcards for command arguments no go match again, so see the sudoers rule wey you fit write instead.
Wetin sudo-rs change for Ubuntu
Ubuntu 26.04 LTS dey ship with 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 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 select the original sudo unless you install sudo-rs by hand. This matter go start when you upgrade from Ubuntu 24.04 to 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 differ on a server explain which machine go meet change like this first.
Check which sudo your server is actually running
No use release number take work 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 dey list every installed provider of /usr/bin/sudo and mark the one wey selected. Say package dey installed no mean say dem select am, so read the selection, no be package list.
Both implementations dey packaged 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, still dey for sudo package; wetin change be say e programs get .ws suffix so both fit install together: /usr/bin/sudo.ws and /usr/bin/visudo.ws, alongside cvtsudoers.ws and sudoreplay.ws. Dem verify am against the 26.04 archive for September 2026: dpkg -L sudo dey list the binaries wey get suffix, and sudo-rs ship /usr/bin/sudo-rs beside dem.
Why Ubuntu change go sudo-rs
sudo na setuid root. Any user for the machine fit start am, and e dey start with full privileges, so memory bug inside am fit become 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 dem rewrite am.
The second reason na scope, and na this one dey affect your config. Original sudo don gather plenty features for three decades, and every feature mean more code wey dey run as root. sudo-rs implement only subset on purpose. Anything wey the authors judge say na niche or e fit cause harm, dem leave am out. So sudoers construct wey work for years fit simply no dey available. Your wildcard rule na one of dem.
Memory safety remove one class of bug. E no make program free from bugs, and sudo-rs don ship security fixes of im own since e become the default. Patch am like any other software.
Rules wey still dey work for sudoers
Na the same file still be that file. sudo-rs dey read /etc/sudoers and the drop-in files for /etc/sudoers.d/, and the normal things wey server operator dey write, e support:
deploy ALL=(ALL:ALL) ALL, and group formats like%sudo ALL=(ALL:ALL) ALL- the
NOPASSWD:andPASSWD:tags User_Alias,Runas_Alias,Host_AliasandCmnd_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 arguments at all - command wey
*follow as the final argument, wey allow any trailing arguments - directory path wey end for
/, wey allow any command inside that directory !to remove command from a list- useful subset of
Defaults, includingsecure_path,env_keep,env_check,timestamp_timeout,passwd_tries,editor,umask,targetpw,rootpwanduse_pty
Two defaults dey behave differently, and dem dey confuse people. env_reset no fit turn off for sudo-rs: e dey always on. use_pty dey on by default, so the command dey run for its own pseudo-terminal.
Why 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 permit sudo fsck and sudo fsck_exfat, because * dey part of the path wey sudo dey match against the filesystem.
Inside the argument list, sudo-rs only accept two special forms, and neither one be pattern. "" mean no arguments. A final * mean any extra arguments after am. 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 anything wey you intend:
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*app-* na pattern wey dey middle of an argument. sudo-rs no expand am, so the rule no cover systemctl restart app-api and sudo reject the command. Two commands go show you the truth about any rule for your own server: sudo -l -U deploy, when you run am 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 edit anyhow.
Wildcard rule always be loophole
For the original sudo, dem go join the arguments wey you type into one string, then match am against the rule argument string with glob. Glob dey match whitespace. Na this part almost everybody dey miss.
sudo-rs documentation show the clearest example. 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 with .txt”.
The same thing apply to the systemctl example. Because dem compare the arguments as one joined string, trailing pattern still match anything wey you append after am. So restart app-* cover restart app-api plus any extra arguments wey caller add. Pattern inside one argument dey expose the arguments around am, and na for arguments command power dey. sudo-rs reject this construct instead of trying to make am safe, because no generally safe form of am dey.
Replace wildcard with command list wey clear
Most 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_STATUSMake sure path correct. Rule wey name /bin/systemctl for system where binary na /usr/bin/systemctl no go ever match, and the failure go look exactly like permission 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 conflict with your edit:
sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deployName the file without dot and without trailing tilde. Original sudo dey ignore files for sudoers.d wey their names get dot, so 90-deploy.conf na classic silent no-op. Following this convention no cost anything.
Use root-owned wrapper when the list too long
When the allowed set too big to list, move the decision comot sudoers go 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-restartThe sudoers side go then name one command:
deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart *The trailing * dey okay here because na the script, not sudo, dey decide wetin allowed. This one only hold 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 am 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, reading the drwxr-xr-x permission string fit take just five minutes to learn. The same rule cover the directory too: /usr/local/sbin no suppose writable by the account either, because writable directory mean say person fit replace the whole file.
Give the job im own account instead of sudo rule
The better question na often why the command need root at all. Service wey dey run as im own user fit let that user manage am, and no sudoers line go dey involved. For system units, systemd 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. Either way, the account wey dey do the work suppose exist only for that work. Na the same reason behind least-privilege user accounts for VPS.
Wetin else 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, and remember say env_reset dey always on, so anything wey dem 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-inside-directory part wey dey out of scope.
INTERCEPT, wey try stop shell escapes from command wey dem permit, no dey implemented. E no ever fit stop determined user anyway. If rule allow person run editor or interpreter as root, the person get root access, and no sudo option fit change that.
Session recording no dey implemented, so no I/O log and no sudoreplay. Logging 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.
You suppose switch back to sudo.ws?
You fit do am, and during the 26.04 cycle, the original one still dey packaged exactly because of this reason.
sudo apt install sudo
update-alternatives --config sudo
sudo update-alternatives --set sudo /usr/bin/sudo.wsCopy the exact paths from the --config output instead of this page, because na the list wey your own system go accept. If you wan go back to sudo-rs later, set the alternative to the sudo-rs binary path from that same list.
Keep another SSH session open, logged in and idle, before you touch anything wey fit affect sudo. If sudoers file no parse, or alternative point to binary wey no dey installed, you fit lose every way to become root for remote box. This habit join everything else wey you 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 was granting more access than the author understood.
FAQ
Dem stop my sudoers wildcard rule from working for Ubuntu 26.04 because of wetin?
Because Ubuntu 26.04 LTS select sudo-rs as the default sudo, and sudo-rs no dey match wildcard patterns inside command arguments. E allow wildcard for the command file name, "" to mean say no arguments dey, and one * as the final argument. Rule like /usr/bin/systemctl restart app-* put pattern inside the middle of argument, so e no grant anything and the command dey refused. Run sudo -l -U deploy as root to see wetin the account really get, then replace the rule with exact commands or with root-owned wrapper script.
How I fit switch back to the original sudo for Ubuntu 26.04?
The original dey inside sudo package, and the binaries get .ws suffix. Install am with sudo apt install sudo, 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 second SSH session open while you change am. This no 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 the caller fit control na known way to change how the 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.