← Back to Feed CACHED · 2026-09-24 14:26:21 · CACHE_KEY CVE-2026-96512
CVE-2026-96512 · CWE-863 · Disclosed 2026-09-23

A flaw was found in sudo.

ASSESSED — NOISGATE
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Like finding a hotel that only locks its pool at night — except almost no hotel has a pool

CVE-2026-96512 affects sudo's NOTBEFORE and NOTAFTER time-based authorization feature. When an administrator writes a sudoers rule that restricts command execution to specific time windows using timestamps that omit the trailing 'Z' UTC indicator, sudo evaluates the time constraint using the calling user's TZ environment variable. Because sudo is a setuid-root program, a local user can set TZ to an extreme offset (e.g., TZ=UTC+25) to shift the authorization window by up to ~25 hours, causing expired or not-yet-valid rules to pass validation. All sudo versions prior to 1.9.16 are affected. RHEL 7 through 10, and by extension every major Linux distro shipping sudo <1.9.16, carries the flaw. Critically, authentication is never bypassed — only the time-window check is defeated. The user must already be the named subject of the sudoers rule and must still authenticate normally.

Red Hat rates this HIGH (7.8) with C:H/I:H/A:H, which models the *theoretical maximum* impact of whatever command the sudoers rule authorizes. That scoring is technically defensible in isolation, but it completely ignores that the prerequisite configuration is vanishingly rare. The NOTBEFORE/NOTAFTER feature is a niche sudoers extension that virtually no enterprise deploys in production — it doesn't appear in default configurations, LDAP-backed sudoers schemas rarely expose it, and Ansible/Puppet/Chef sudo modules don't template it. Among the sliver of organizations that *do* use time-based sudo restrictions, the timestamps must further lack the 'Z' suffix to be exploitable. The vendor score treats this like a standard local-privilege-escalation bug; in reality it is a narrow policy-bypass that grants no new privileges — only a wider time window on privileges the user already holds.

"Sudo time-window bypass requires ultra-rare config; 99%+ of fleets are unaffected."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Attacker obtains local shell access

The attacker must already have an interactive shell on the target host as a regular (non-root) user. This is the baseline requirement for all local sudo attacks. Remote exploitation is not possible — there is no network attack vector.
Conditions required:
  • Valid local user account on the target host
  • Interactive shell access (SSH, console, etc.)
Where this breaks in practice:
  • Requires prior compromise or insider access — this is a post-auth, post-access position
  • Most internet-facing Linux services run as service accounts without interactive shells
Detection/coverage: EDR/audit logs capture new interactive sessions; auditd rules on execve for shell invocations.
STEP 02

Sudoers rule with NOTBEFORE/NOTAFTER exists for the user

The target system must have a sudoers rule that names the attacker's user (or a group they belong to) AND uses NOTBEFORE or NOTAFTER timestamps to constrain when the rule is valid. This is the critical gating condition — without such a rule, the vulnerability has zero impact. The timestamps must omit the trailing 'Z' suffix, causing sudo to interpret them in local time via TZ.
Conditions required:
  • Sudoers rule with NOTBEFORE/NOTAFTER targeting the attacker's user or group
  • Timestamps written without trailing 'Z' (UTC) indicator
  • Sudo version < 1.9.16
Where this breaks in practice:
  • NOTBEFORE/NOTAFTER is an extremely niche feature — fewer than 1% of enterprise sudo configurations use it
  • Default sudoers files on all major distros contain zero NOTBEFORE/NOTAFTER rules
  • LDAP/SSSD-backed sudo schemas (FreeIPA, RHDS) rarely expose time-based attributes
  • Configuration management tools (Ansible, Puppet, Chef) do not template this feature by default
Detection/coverage: Audit with grep -rE 'NOT(BEFORE|AFTER)=' /etc/sudoers /etc/sudoers.d/ — if empty, you are not affected.
STEP 03

Set TZ to extreme offset

The attacker sets the TZ environment variable to an extreme value such as TZ=UTC+25 or TZ=UTC-25 before invoking sudo. Because sudo is setuid-root, it inherits the user's environment including TZ. The mktime() call inside sudo's time evaluation re-reads TZ each invocation, applying the attacker-chosen offset to the NOTBEFORE/NOTAFTER comparison. No special tools are required — export TZ=UTC+25 is sufficient.
Conditions required:
  • Ability to set environment variables (standard for any shell user)
  • Target rule's time window is within ~25 hours of current real time
Where this breaks in practice:
  • Trivial to execute but completely dependent on Step 2 precondition existing
  • sudo may log the unusual TZ value in auth logs if verbose logging is enabled
Detection/coverage: Monitor sudo auth logs for unusual TZ values; auditd can capture setenv calls before execve of /usr/bin/sudo.
STEP 04

Execute time-restricted sudo command outside permitted window

With the shifted timezone, sudo's NOTBEFORE/NOTAFTER check passes and the user executes the authorized command outside its intended time window. The impact is exactly the same as running the command during the permitted window — no escalation beyond what the rule already grants. If the rule allows ALL commands, the user gets root; if it allows only /usr/bin/systemctl restart httpd, that's all they get.
Conditions required:
  • Steps 1-3 completed successfully
  • The sudoers rule grants meaningful privilege worth exploiting outside the time window
Where this breaks in practice:
  • The attacker already has this exact privilege during the permitted window — they gain no *new* capability, only a *wider schedule*
  • Most time-restricted rules grant narrow commands, not blanket root access
Detection/coverage: All executions are logged normally by sudo — journalctl -u sudo or /var/log/auth.log will show the command execution with full user and command details.
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNone observed. Not listed on CISA KEV. No reports from threat intelligence vendors, DFIR teams, or honeypot networks as of 2026-09-24.
Proof of ConceptNo public PoC repository or exploit code. Exploitation is trivial (export TZ=UTC+25 && sudo <command>) but requires the rare NOTBEFORE/NOTAFTER configuration. No Metasploit/Nuclei modules exist.
EPSS ScoreNot yet scored (disclosed 2026-09-23). Expected to be very low (<0.01) given local-only vector and niche prerequisite.
KEV StatusNot listed. No evidence of active exploitation warranting KEV inclusion.
CVSS VectorCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — Local attack, low complexity, low privileges, no user interaction. The C:H/I:H/A:H models theoretical maximum of the authorized sudo command, not actual privilege gain from the bypass itself.
Affected VersionsAll sudo versions prior to 1.9.16. Upstream fix in commit sudo-project/sudo@1820a34. Affects RHEL 7, 8, 9, 10, and all distros shipping unpatched sudo.
Fixed Versionssudo ≥ 1.9.16 (upstream). Distro backport status: RHEL errata pending as of 2026-09-24. Current stable: sudo 1.9.17p2.
Scanning / ExposureNot remotely exploitable — Shodan/GreyNoise/Censys are irrelevant. Local detection only: grep -rE 'NOT(BEFORE|AFTER)=' /etc/sudoers /etc/sudoers.d/ identifies affected hosts in seconds.
Disclosure TimelineReported to Red Hat 2026-08-28 by Ermenson Junior (independent researcher). Public disclosure 2026-09-23. Red Hat Bugzilla #2539327.
ReporterErmenson Junior, independent security researcher.

Sources.

  1. Red Hat CVE Page — CVE-2026-96512
  2. NixOS/nixpkgs Tracking Issue #566431
  3. Red Hat Bugzilla #2539327
  4. OffSeq Threat Radar — CVE-2026-96512
  5. Sudo Stable Releases
  6. Sudoers Manual — NOTBEFORE/NOTAFTER Documentation
  7. Strix.ai CVE-2026-96512 Summary
  8. ThreatInt CVE-2026-96512
04 · The Call

Final Verdict
DOWNGRADED to LOW (3.2/10)

Why this verdict

  • Precondition rarity is the dominant factor. The NOTBEFORE/NOTAFTER feature is a niche sudoers extension used by fewer than 1% of enterprise Linux hosts. Default configurations across all major distros contain zero time-based rules. The vulnerability simply does not exist on hosts without this configuration — and that's 99%+ of any fleet.
  • Double-gated configuration. Even among the tiny fraction using NOTBEFORE/NOTAFTER, timestamps must specifically omit the 'Z' UTC suffix. Following the RFC 4517 convention (appending 'Z') fully neutralizes the bug. This further narrows the exploitable population to a fraction of a fraction.
  • No new privileges gained. The attacker already holds the sudo authorization granted by the rule — they can execute the exact same commands during the permitted window. This bypass extends *when* they can act, not *what* they can do. The CVSS C:H/I:H/A:H models the sudo command's impact ceiling, not the marginal impact of the time-window shift.
  • Local access required, post-compromise position. AV:L/PR:L means the attacker already has a shell and valid credentials. This is a privilege they must obtain through a separate, prior attack chain.
  • Role multiplier: Sudo is universal but the vulnerable config is not. Sudo is installed on ~100% of Linux hosts including high-value roles (hypervisors, CI/CD, DCs, databases). However, the exploitable condition (NOTBEFORE/NOTAFTER without Z) is virtually absent in these roles. FreeIPA, SSSD-backed sudoers, Ansible/Puppet templates, and cloud IAM-integrated sudo solutions do not generate time-based rules. The chain does NOT succeed in high-value roles under standard configurations, so the deployment-role floor does not elevate this beyond LOW.
  • No exploitation, no PoC ecosystem, no KEV. Zero evidence of real-world abuse. The trivial exploit mechanics (just set TZ) combined with the zero adoption of the prerequisite config means no attacker ROI.

Why not higher?

Upgrading to MEDIUM would require either meaningful prevalence of the precondition configuration or evidence that NOTBEFORE/NOTAFTER-without-Z is common in a specific high-value deployment pattern. Neither condition is met. The feature is documented as an extension, is absent from all default configs, and is not generated by any mainstream configuration management tooling. The attack also grants no new capability — only a scheduling extension of existing privilege.

Why not lower?

Dropping to IGNORE would disregard the theoretical scenario where a security-conscious organization deliberately uses time-based sudo restrictions as a compensating control (e.g., limiting DBA root access to maintenance windows). In that narrow case, bypassing the time check defeats a deliberate security boundary. The 3.2 score preserves this as a backlog item for the rare environment where it matters.

05 · Compensating Control

1
LOW 3.2IGNORE 0.0
SEVERITY REDUCED
Append 'Z' to all NOTBEFORE/NOTAFTER timestamps in sudoers — This is the definitive mitigation. Change timestamps like NOTAFTER=20261231235959 to NOTAFTER=20261231235959Z. When the trailing Z is present, sudo interprets the timestamp as UTC and ignores the TZ environment variable entirely. Run grep -rE 'NOT(BEFORE|AFTER)=' /etc/sudoers /etc/sudoers.d/ to identify affected rules, then edit. As a LOW-severity finding, there is no noisgate mitigation SLA — treat this as backlog hygiene and include it in your next sudoers configuration audit cycle.
2
LOW 3.2IGNORE 0.0
SEVERITY REDUCED
Upgrade sudo to ≥ 1.9.16 — The upstream fix in sudo 1.9.16 strips the user-supplied TZ from sudo's working environment entirely, preventing the bypass regardless of timestamp format. Apply via distro package updates when errata are available. Per noisgate remediation SLA for LOW, target within the backlog cycle (no hard deadline, but good hygiene).
3
LOW 3.2IGNORE 0.0
SEVERITY REDUCED
Audit sudoers for NOTBEFORE/NOTAFTER usage fleet-wide — Run grep -rE 'NOT(BEFORE|AFTER)=' /etc/sudoers /etc/sudoers.d/ across your fleet via your configuration management or EDR tool. If the result is empty on all hosts (overwhelmingly likely), document that finding and close this CVE as not-applicable for your environment. No SLA pressure — this is a triage-to-close action.
What doesn't work
  • Restricting TZ in env_reset / env_delete — sudo's env_reset option (enabled by default) does filter most environment variables, but TZ is on the default env_keep list in many distro configurations. Even if you remove TZ from env_keep, the underlying mktime() reads TZ before sudo's environment sanitization completes in vulnerable versions. The only reliable fix is the upstream patch or appending 'Z' to timestamps.
  • SELinux / AppArmor confinement — MAC policies constrain what sudo-executed commands can do, but they do not intercept or validate the TZ environment variable during sudo's own authorization parsing. The bypass occurs before the target command runs.
  • Removing sudo — impractical and creates far more operational risk than this vulnerability warrants.
06 · Verification

Crowdsourced verification payload.

Run this script on each target Linux host as any user with read access to /etc/sudoers (typically root). Invoke with: sudo bash check_cve_2026_96512.sh. Exit code 0 = PATCHED or not affected, exit code 1 = VULNERABLE, exit code 2 = UNKNOWN.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_96512.sh — Detect CVE-2026-96512 (sudo TZ NOTBEFORE/NOTAFTER bypass)
# Run as root or a user who can read /etc/sudoers and /etc/sudoers.d/*
# Exit codes: 0 = PATCHED/not affected, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

RESULT="UNKNOWN"

# Step 1: Check if sudo is installed
if ! command -v sudo &>/dev/null; then
  echo "PATCHED — sudo is not installed on this host."
  exit 0
fi

# Step 2: Get sudo version
SUDO_VER=$(sudo -V 2>/dev/null | head -1 | grep -oP '[0-9]+\.[0-9]+\.[0-9]+[a-z]*[0-9]*' || true)
if [[ -z "$SUDO_VER" ]]; then
  echo "UNKNOWN — could not determine sudo version."
  exit 2
fi
echo "[*] Detected sudo version: $SUDO_VER"

# Step 3: Version comparison — fixed in 1.9.16
# Extract major.minor.patch
IFS='.' read -r MAJOR MINOR PATCH_RAW <<< "$SUDO_VER"
PATCH=$(echo "$PATCH_RAW" | grep -oP '^[0-9]+' || echo "0")

VER_FIXED=0
if [[ $MAJOR -gt 1 ]]; then
  VER_FIXED=1
elif [[ $MAJOR -eq 1 && $MINOR -gt 9 ]]; then
  VER_FIXED=1
elif [[ $MAJOR -eq 1 && $MINOR -eq 9 && $PATCH -ge 16 ]]; then
  VER_FIXED=1
fi

if [[ $VER_FIXED -eq 1 ]]; then
  echo "PATCHED — sudo $SUDO_VER >= 1.9.16 (upstream fix applied)."
  exit 0
fi

# Step 4: Version is vulnerable; check if NOTBEFORE/NOTAFTER is actually in use
echo "[*] sudo version $SUDO_VER is below 1.9.16 — checking sudoers configuration..."

HITS=""
for f in /etc/sudoers /etc/sudoers.d/*; do
  [[ -r "$f" ]] || continue
  MATCH=$(grep -nE 'NOT(BEFORE|AFTER)=' "$f" 2>/dev/null || true)
  if [[ -n "$MATCH" ]]; then
    # Check if any of these lack trailing Z or timezone offset
    NO_Z=$(echo "$MATCH" | grep -vE 'NOT(BEFORE|AFTER)=[0-9]{8,14}(Z|[+-][0-9]{4})' || true)
    if [[ -n "$NO_Z" ]]; then
      HITS="${HITS}${f}:\n${NO_Z}\n"
    fi
  fi
done

if [[ -n "$HITS" ]]; then
  echo "VULNERABLE — sudo $SUDO_VER with NOTBEFORE/NOTAFTER timestamps lacking 'Z' suffix:"
  echo -e "$HITS"
  exit 1
else
  echo "PATCHED — sudo $SUDO_VER is technically vulnerable but no NOTBEFORE/NOTAFTER rules without 'Z' found. Not exploitable in current config."
  exit 0
fi
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously