sudo-rs en Ubuntu: cambios en sudoers y comodines
Ubuntu 26.04 usa sudo-rs por defecto: los comodines en argumentos dejan de coincidir. Revise sus reglas sudoers y sustitúyalos por una sintaxis compatible.
Qué cambia sudo-rs en Ubuntu
Ubuntu 26.04 LTS incluye sudo-rs como sudo predeterminado, por lo que el comando sudo en un servidor recién instalado ejecuta la reimplementación en Rust en lugar del programa original en C. La mayoría de los archivos sudoers siguen funcionando exactamente igual. La regla que deja de funcionar es la que contiene un comodín dentro de los argumentos de un comando, porque sudo-rs no compara patrones glob con el texto de los argumentos.
Ubuntu 25.10 hizo primero el cambio y Ubuntu 26.04 LTS lo mantuvo. Ubuntu 24.04 LTS no está afectado, porque sigue seleccionando el sudo original, salvo que instale sudo-rs manualmente. Esto resulta relevante al actualizar de Ubuntu 24.04 a 26.04 o al preparar un servidor nuevo con la versión más reciente. Si también administra versiones intermedias, cómo difieren las versiones LTS e intermedias de Ubuntu en un servidor explica qué equipo recibe primero un cambio de este tipo.
Compruebe qué sudo ejecuta realmente el servidor
No lo determine a partir del número de versión. Consulte la máquina.
sudo --version
update-alternatives --config sudo
dpkg -l 'sudo*'Confíe en sudo --version de su propio equipo antes que en cualquier tabla de versiones de Internet, incluida esta página. update-alternatives --config sudo es la otra mitad de la respuesta: muestra todos los proveedores instalados de /usr/bin/sudo y marca el seleccionado. Que un paquete esté instalado no significa que esté seleccionado. Por tanto, lea la selección, no la lista de paquetes.
Durante la transición se empaquetan ambas implementaciones. La de Rust es sudo-rs, con la versión 0.2.13 en 26.04 a fecha de agosto de 2026. La original, mantenida por Todd C. Miller, sigue siendo el paquete sudo. El cambio es que sus programas llevan el sufijo .ws, de modo que ambos pueden instalarse a la vez: /usr/bin/sudo.ws y /usr/bin/visudo.ws, junto con cvtsudoers.ws y sudoreplay.ws. Verificado con el archivo de 26.04 en septiembre de 2026: dpkg -L sudo muestra los binarios con sufijo y sudo-rs incluye /usr/bin/sudo-rs junto a ellos.
Por qué Ubuntu cambió a sudo-rs
sudo utiliza el bit setuid de root. Cualquier usuario del sistema puede iniciarlo y se ejecuta con privilegios completos, por lo que un error de memoria en su interior se convierte en un exploit local para obtener root. CVE-2021-3156 fue exactamente eso: un desbordamiento del búfer de la pila alcanzable por cualquier usuario local que permaneció aproximadamente diez años en código publicado. Rust detecta esta clase de errores en tiempo de compilación. Ese es el argumento principal para reescribirlo.
El segundo motivo es el alcance, y es el que afecta a su configuración. El sudo original ha acumulado un conjunto amplio de funciones durante tres décadas. Cada función añade más código que se ejecuta como root. sudo-rs implementa deliberadamente un subconjunto. Sus autores omitieron cualquier función que consideraron específica o perjudicial. Por eso, una construcción de sudoers que funcionó durante años puede no estar implementada. Su regla con comodines es una de ellas.
La seguridad de memoria elimina una clase de errores. No hace que un programa esté libre de errores. sudo-rs también ha publicado correcciones de seguridad desde que se convirtió en la opción predeterminada. Manténgalo actualizado como cualquier otro programa.
Qué reglas de sudoers siguen funcionando
El archivo es el mismo. sudo-rs lee /etc/sudoers y los archivos adicionales de /etc/sudoers.d/. También admite las reglas habituales que escribe un administrador de servidores:
deploy ALL=(ALL:ALL) ALLy las formas para grupos, como%sudo ALL=(ALL:ALL) ALL- las etiquetas
NOPASSWD:yPASSWD: User_Alias,Runas_Alias,Host_AliasyCmnd_Alias- un comando con una lista exacta de argumentos, por ejemplo
/usr/bin/systemctl restart app-api - un comando seguido de
"", que permite ejecutar el comando sólo sin argumentos - un comando seguido de
*como argumento final, que permite cualquier argumento adicional - una ruta de directorio que termine en
/, que permite cualquier comando de ese directorio !para excluir un comando de una lista- un subconjunto útil de
Defaults, incluidossecure_path,env_keep,env_check,timestamp_timeout,passwd_tries,editor,umask,targetpw,rootpwyuse_pty
Dos valores predeterminados se comportan de forma diferente y pueden causar problemas. env_reset no se puede desactivar en sudo-rs: siempre está habilitado. use_pty está habilitado de forma predeterminada, por lo que el comando se ejecuta en su propio pseudo-terminal.
Por qué la regla comodín de sudoers dejó de coincidir
Los comodines siguen permitidos en un lugar: el nombre de archivo del comando. Una regla con %ops ALL = /sbin/fsck* todavía permite sudo fsck y sudo fsck_exfat, porque * forma parte de la ruta que se compara con el sistema de archivos.
Dentro de la lista de argumentos, sudo-rs acepta sólo dos formas especiales, y ninguna es un patrón. "" significa que no hay argumentos. Un * final significa cualquier argumento adicional. Todos los demás argumentos se comparan como texto literal. Por eso %ops ALL = /sbin/service ntp * es válido: ntp es literal y * está al final. Sin embargo, una regla como la siguiente no concede nada de lo que pretendía:
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*app-* es un patrón en medio de un argumento. sudo-rs no lo expande, por lo que la regla no incluye systemctl restart app-api y sudo rechaza el comando. Dos comandos muestran la situación real de cualquier regla en su propio servidor: sudo -l -U deploy, ejecutado como root, muestra lo que esa cuenta puede ejecutar realmente, y sudo visudo -c indica si el archivo se puede analizar. Ejecútelos antes de empezar a editar al azar.
La regla comodín siempre fue una vulnerabilidad
En el sudo original, los argumentos que se escriben se unen en una sola cadena y se comparan mediante un patrón glob con la cadena de argumentos de la regla. Un patrón glob coincide con espacios en blanco. Ese es el detalle que casi todo el mundo pasa por alto.
La documentación de sudo-rs muestra el caso con mayor claridad. Una regla /bin/rm *.txt también permite sudo rm -rf /home .txt, porque el único * absorbe -rf /home y la cadena resultante sigue terminando en .txt. La regla se interpreta como «sólo archivos de texto». En realidad significa «cualquier argumento, siempre que la línea termine en .txt».
Lo mismo ocurre con el ejemplo de systemctl. Como los argumentos se comparan como una sola cadena unida, un patrón final también coincide con todo lo que se añada después. Por tanto, restart app-* incluye restart app-api y cualquier argumento adicional que añada el usuario. Un patrón dentro de un argumento deja expuestos los argumentos que lo rodean, y los argumentos son los que determinan las capacidades de un comando. sudo-rs rechaza esta construcción en lugar de intentar hacerla segura, porque no existe una forma general segura de usarla.
Sustituya el comodín por una lista de comandos explícita
La mayoría de las reglas con comodines existen porque alguien no quería escribir cuatro líneas. Escriba las cuatro líneas.
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_STATUSIndique la ruta correcta. Una regla que especifica /bin/systemctl en un sistema donde el binario está en /usr/bin/systemctl nunca coincide, y el fallo es idéntico al de un problema de permisos. Confírmelo con command -v systemctl y pegue la salida.
Coloque la regla en su propio archivo de configuración adicional en lugar de /etc/sudoers, para que una actualización del paquete nunca entre en conflicto con su modificación:
sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deployAsigne al archivo un nombre sin punto y sin una tilde final. El sudo original ignora los archivos de sudoers.d cuyos nombres contienen un punto, por lo que 90-deploy.conf no produce ningún efecto y pasa inadvertido. Mantener esta convención no cuesta nada.
Use un wrapper propiedad de root cuando la lista sea larga
Cuando el conjunto permitido sea demasiado grande para enumerarlo, traslade la decisión fuera de sudoers a un programa pequeño que pertenezca a root.
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-restartEn sudoers sólo se especifica un comando:
deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart *El * final es aceptable aquí porque el script, y no sudo, decide qué está permitido. Esto sólo es válido mientras el script pertenezca a root y nadie más pueda escribir en él. Si deploy puede escribir en el archivo, deploy puede reemplazar su contenido y ejecutar cualquier cosa como root, lo que es peor que la regla con comodín que eliminó. Compruebe los permisos con ls -l y, si el resultado no le resulta evidente, aprender a leer la cadena de permisos drwxr-xr-x lleva cinco minutos. La misma regla se aplica al directorio: /usr/local/sbin tampoco debe permitir escritura a la cuenta, porque un directorio con permisos de escritura permite reemplazar el archivo completo.
Asigne al trabajo su propia cuenta en lugar de una regla de sudo
La pregunta adecuada suele ser por qué el comando necesita privilegios de root. Un servicio que se ejecuta con su propio usuario puede ser administrado por ese usuario, sin añadir ninguna línea a sudoers. Para las unidades del sistema, systemd ya delega esa decisión en polkit, por lo que una regla puede especificar una unidad y un operador:
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;
}
});Guarde esto como /etc/polkit-1/rules.d/50-app-api.rules y deploy puede ejecutar systemctl restart app-api sin usar sudo. Pruébelo desde el contexto exacto que lo utilizará, porque una regla que funciona en su sesión SSH debe confirmarse desde cron antes de depender de ella. En cualquier caso, la cuenta que realiza el trabajo debe existir exclusivamente para ese trabajo. Es el mismo principio que se aplica a las cuentas de usuario con privilegios mínimos en un VPS.
Qué más deja fuera sudo-rs
sudo -E no está implementado. Defina las variables que necesite con Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". Recuerde que env_reset siempre está activo, por lo que todo lo que no se conserve se elimina.
El almacenamiento centralizado de sudoers en LDAP ya no está disponible. sudoers.ldap y cvtsudoers no están implementados, y el paquete sudo-ldap se eliminó en 26.04. La autenticación LDAP mediante PAM o SSSD sigue funcionando. Lo que queda fuera de alcance es la parte de la política almacenada en un directorio.
INTERCEPT, que intentaba impedir las salidas al shell desde un comando permitido, no está implementado. De todos modos, no podía impedir a un usuario decidido. Si una regla permite ejecutar un editor o un intérprete como root, ese usuario tiene acceso de root. Ninguna opción de sudo cambia ese hecho.
La grabación de sesiones no está implementada. Por tanto, no hay ningún registro de E/S ni sudoreplay. Los registros se envían únicamente a syslog. Tampoco existe la opción logfile para redirigirlos a otro destino, por lo que los mensajes de sudo llegan al destino donde el sistema ya envía syslog.
¿Debería volver a sudo.ws?
Puede hacerlo. Durante el ciclo 26.04, el paquete original se mantiene precisamente por este motivo.
sudo apt install sudo
update-alternatives --config sudo
sudo update-alternatives --set sudo /usr/bin/sudo.wsCopie las rutas exactas de la salida de --config, no las de esta página. Esa salida contiene la lista que aceptará su propio sistema. Para volver después a sudo-rs, establezca la alternativa en la ruta del binario de sudo-rs que aparece en la misma lista.
Mantenga abierta una segunda sesión SSH, con la sesión iniciada y en espera, antes de cambiar cualquier elemento que afecte a sudo. Un archivo sudoers que no se pueda analizar o una alternativa que apunte a un binario no instalado pueden dejarle sin forma de convertirse en root en un sistema remoto. Este hábito debe formar parte de todo lo que haga durante los primeros diez minutos en un VPS nuevo.
Considere la vuelta como un plazo, no como una solución. Le da una semana para reescribir las reglas correctamente. La reescritura merece la pena por sí misma, porque cada regla con comodines que elimine concedía más permisos de los que su autor había previsto.
FAQ
¿Por qué dejó de funcionar mi regla comodín de sudoers en Ubuntu 26.04?
Porque Ubuntu 26.04 LTS selecciona sudo-rs como sudo predeterminado, y sudo-rs no compara patrones comodín dentro de los argumentos de un comando. Permite un comodín en el nombre de archivo del comando, "" para indicar que no hay argumentos y un único * como argumento final. Una regla como /usr/bin/systemctl restart app-* coloca un patrón en medio de un argumento, por lo que no concede ningún permiso y el comando se rechaza. Ejecute sudo -l -U deploy como root para comprobar lo que realmente tiene la cuenta y, después, sustituya la regla por los comandos exactos o por un script envoltorio propiedad de root.
¿Cómo vuelvo al sudo original en Ubuntu 26.04?
El original se incluye en el paquete sudo, cuyos binarios llevan el sufijo .ws. Instálelo con sudo apt install sudo y, después, seleccione esa alternativa con sudo update-alternatives --set sudo /usr/bin/sudo.ws. Ejecute primero update-alternatives --config sudo para consultar las rutas exactas que ofrece el sistema y mantenga abierta una segunda sesión SSH mientras realiza el cambio. Esto no recupera sudo-ldap, que se eliminó de 26.04 independientemente de la implementación seleccionada.
¿Lee sudo-rs el mismo archivo /etc/sudoers?
Sí. sudo-rs lee /etc/sudoers y los archivos adicionales del directorio /etc/sudoers.d/, con la misma sintaxis para usuarios, grupos, alias, especificaciones run-as y la etiqueta NOPASSWD. Implementa un subconjunto del lenguaje de sudoers, por lo que las diferencias aparecen como construcciones que faltan, no como construcciones con un comportamiento diferente. Edite con sudo visudo y, después, compruebe la configuración con sudo visudo -c antes de cerrar la sesión.
¿Qué sustituye a sudo -E en sudo-rs?
sudo -E no está implementado, y ya se desaconsejaba en el sudo original, porque entregar a un proceso root un entorno controlado por el usuario es una forma conocida de modificar el comportamiento de ese proceso. En su lugar, indique en sudoers las variables que realmente necesita, con una línea como Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". env_reset está siempre activo en sudo-rs y no se puede desactivar, por lo que se elimina cualquier variable que no conserve.