Description
Three sudo defaults, set with Defaults lines in /etc/sudoers or /etc/sudoers.d/:
use_pty: run each command in a new pseudo-terminal, so it cannot inject input into the user's terminal after sudo exits;logfile: write every sudo command to a dedicated file, in addition to syslog;timestamp_timeout: how many minutes a successful authentication is cached before sudo asks for the password again.
Ubuntu sets use_pty in /etc/sudoers since 22.04 (not on 20.04) and caches credentials for
15 minutes. With the original sudo, the effective values are read with sudo -V as root, which
merges every sudoers file.
On Ubuntu 26.04 the sudo command is sudo-rs. It always runs commands in a pseudo-terminal
unless !use_pty is set, sends every command to syslog (the journal), and has no logfile
option: visudo rejects that line as an unknown setting. Its sudo -V only prints the version,
so the checks read the sudoers files instead, and the logfile check is not applicable.
Rationale
Without use_pty, a malicious program run through sudo can keep running in the background and
push keystrokes into the user's shell. A dedicated log file keeps a readable record of
privileged commands even if syslog is lost or flooded. A short cache limits how long an
unattended terminal can run privileged commands without a password.
Impact
Some interactive programs behave differently in a pseudo-terminal (rare). Users type their password again after {{ timestamp_timeout }} minutes of not using sudo.
Applies when
Detected: when: A sudo command is installed (sudo or sudo-rs) A scanner reports the control not applicable when one is false.
Setting
| Location | /etc/sudoers.d/60-cirsec |
| Default | 20.04: no use_pty; 22.04 and later: use_pty; no log file, 15 minutes |
| Recommended | use_pty, logfile={{ log_file }} (not with sudo-rs), timestamp_timeout at most {{ timestamp_timeout }} |
Parameters
| Parameter | Core | Server | Server hardened | Desktop | Desktop hardened | Bounds |
|---|---|---|---|---|---|---|
log_filestring. Path of the sudo log file. Not used by sudo-rs, which logs to syslog only. | /var/log/sudo.log | /var/log/sudo.log | /var/log/sudo.log | /var/log/sudo.log | /var/log/sudo.log | |
timestamp_timeoutinteger, minutes. Maximum number of minutes sudo caches credentials. | 15 | 15 | 5 | 15 | 5 | 0 to 15 |
The value used is your override (tailoring file), else the profile's, else the one of the profile it extends, else the default. Bounds limit what an override may set.
Audit
With the original sudo, run sudo -V as root and check that:
- it prints
Always run commands in a pseudo-tty; Path to log file:is set;Authentication timestamp timeout:is at most {{ timestamp_timeout }} minutes.
With sudo-rs (sudo --version starts with sudo-rs), read /etc/sudoers and
/etc/sudoers.d/*: there is no Defaults !use_pty, and the last timestamp_timeout is at most
{{ timestamp_timeout }} (15 when absent).
Automated: every check must pass. Scanners report each check by its id.
use-pty
sudo runs commands in a pseudo-terminal.
script: |
if sudo --version 2>/dev/null | head -n 1 | grep -q '^sudo-rs'; then
l=$(cat /etc/sudoers /etc/sudoers.d/* 2>/dev/null | grep -E '^[[:space:]]*Defaults.*![[:space:]]*use_pty')
[ -z "$l" ] || { echo "sudo-rs: $l"; exit 1; }
echo "sudo-rs: use_pty (default, not disabled)"
exit 0
fi
sudo -V 2>/dev/null | grep -q 'Always run commands in a pseudo-tty' || { echo "use_pty not set"; exit 1; }
echo "use_pty set"
logfile
sudo writes to a log file (not applicable to sudo-rs, which only logs to syslog).
script: |
if sudo --version 2>/dev/null | head -n 1 | grep -q '^sudo-rs'; then
echo "sudo-rs has no logfile option; commands are logged to syslog"
exit 2
fi
f=$(sudo -V 2>/dev/null | sed -n 's/^Path to log file: //p')
echo "logfile=${f:-none}"
[ -n "$f" ]
timeout
sudo credential cache lifetime.
script: |
if sudo --version 2>/dev/null | head -n 1 | grep -q '^sudo-rs'; then
t=$(cat /etc/sudoers /etc/sudoers.d/* 2>/dev/null | grep -E '^[[:space:]]*Defaults' \
| sed -n 's/.*timestamp_timeout[[:space:]]*=[[:space:]]*\([0-9-]*\).*/\1/p' | tail -n 1)
t=${t:-15}
else
t=$(sudo -V 2>/dev/null | sed -n 's/^Authentication timestamp timeout: \([0-9-]*\).*/\1/p')
fi
echo "timestamp_timeout=${t:-unknown} minutes"
[ -n "$t" ] || exit 3
[ "$t" -ge 0 ] && [ "$t" -le "$CB_TIMESTAMP_TIMEOUT" ]
Remediation
Create /etc/sudoers.d/60-cirsec with visudo -f /etc/sudoers.d/60-cirsec:
Defaults use_pty
Defaults logfile="{{ log_file }}"
Defaults timestamp_timeout={{ timestamp_timeout }}
Leave out the logfile line with sudo-rs (Ubuntu 26.04): sudo-rs rejects it. Remove any
timestamp_timeout with a higher value from other sudoers files.
| Restart | none |
| Disruption | low |
Rollback
Delete /etc/sudoers.d/60-cirsec.
dropin
f=/etc/sudoers.d/60-cirsec
t=$(mktemp)
{
echo '# Written by CIRSEC Baselines CB-UBU-AUTH-005'
echo 'Defaults use_pty'
sudo --version 2>/dev/null | head -n 1 | grep -q '^sudo-rs' || printf 'Defaults logfile="%s"\n' "$CB_LOG_FILE"
echo "Defaults timestamp_timeout=$CB_TIMESTAMP_TIMEOUT"
} >"$t"
if ! visudo -cqf "$t" >/dev/null; then rm -f "$t"; echo "invalid sudoers drop-in" >&2; exit 1; fi
cb_backup "$f"
install -m 0440 -o root -g root "$t" "$f"
rm -f "$t"
Handwritten code reads parameters from CB_<NAME> environment variables. Each release turns these fixes into remediate.sh and an Ansible role per profile: dry run by default, a fix runs only when its check fails.
References
- sudoers(5), Ubuntu manual pages Canonical, vendor-doc, accessed 2026-10-19
- sudo-rs(8), Ubuntu manual pages Canonical, vendor-doc, accessed 2026-10-19
- Ubuntu Server documentation - sudo-rs and Rust coreutils Canonical, vendor-doc, accessed 2026-10-19
- ANSSI-BP-028 v2.0 - Recommandations de configuration d'un système GNU/Linux (R39) ANSSI, guide, accessed 2026-10-19
Mappings
| Framework | ID | Relation | Note |
|---|---|---|---|
| ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0 | R39 | partial | R39 lists several sudo directives; this control covers use_pty, logging and the cache. |
| NIST SP 800-53 Rev. 55.1.1 | AU-2 | related |
How this control relates to the other framework's: equivalent, stricter, looser, partial or related.
Threats mitigated
| Taxonomy | ID |
|---|---|
| MITRE ATT&CK | T1548.003 |
People and lifecycle
| Authors |
|
| Verified | 2026-10-19 by Sn0wAlice on 20.04, Proxmox VM, Ubuntu 20.04 cloud image, kernel 5.4.0-216-generic. Fails on a fresh install (sudo 1.8.31, no use_pty, no log file); drop-in validated by visudo fixes it; sudo of the default user still works; 5 minutes in server-hardened; kept after reboot. |
| Verified | 2026-10-19 by Sn0wAlice on 22.04, Proxmox VM, Ubuntu 22.04 cloud image, kernel 5.15.0-198-generic. Fails on a fresh install (no log file); drop-in validated by visudo fixes it; sudo of the default user still works; 5 minutes in server-hardened; kept after reboot. |
| Verified | 2026-10-19 by Sn0wAlice on 24.04, Proxmox VM, Ubuntu 24.04 cloud image, kernel 6.8.0-147-generic. Fails on a fresh install (no log file); drop-in validated by visudo fixes it; sudo of the default user still works; 5 minutes in server-hardened; kept after reboot. |
| Verified | 2026-10-19 by Sn0wAlice on 26.04, Proxmox VM, Ubuntu 26.04 cloud image, kernel 7.0.0-38-generic. sudo-rs 0.2.13 - use_pty by default passes, logfile not applicable, timeout read from sudoers; drop-in without logfile accepted by visudo, sudo still works, 5 minutes in server-hardened; kept after reboot. |
| Introduced in | v0.1.0 |
| Created, updated | 2026-10-19, 2026-10-19 |
| Translations | fr |