← Back to Feed CACHED · 2026-06-29 21:46:30 · CACHE_KEY CVE-2026-54371
CVE-2026-54371 · CWE-59 · Disclosed 2026-06-29

attr before version 2

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

A locksmith who trusts the address on the envelope without checking which door it actually opens

The attr package ships getfattr and setfattr, the userspace CLIs for reading and writing POSIX extended attributes (xattrs). Versions prior to 2.6.0 resolve path components without protecting against an attacker swapping a directory or filename in the path for a symlink between the time the tool validates the path and the time it operates on it — a classic *TOCTOU symlink race* (CWE-59). When a privileged user (commonly root, during backup/restore, package install, or container image build) runs setfattr or getfattr against a path inside an attacker-writable directory (/tmp, /var/tmp, an unprivileged user's $HOME, an extracted tarball), the attacker can redirect the operation to an arbitrary file — leading to xattr disclosure of files outside the intended scope, or *xattr write* (including security.capability, security.selinux, trusted.*) on files the attacker doesn't own.

Vendor HIGH (7.1) is defensible on paper because writing security.capability to an attacker-chosen binary is a clean local privilege-escalation primitive. In reality, the vector is AV:L/PR:L — the attacker must already be a local unprivileged user AND must win a race against a *concurrently running* root invocation of setfattr or getfattr on a path they can influence. That second condition is the kill switch: outside of well-known automation patterns (backup agents that restore xattrs, container build tooling, package post-install scripts), root rarely runs these utilities on attacker-influenced paths. We assess MEDIUM: real, exploitable in specific automation contexts, but not the broad LPE that 7.1 implies for a general fleet.

"Local symlink TOCTOU in a CLI most admins run interactively — not the fleetwide fire vendor 7.1 suggests."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Establish local foothold as unprivileged user

Attacker needs a shell as any non-root UID on the target — SSH user, web-app service account, CI runner, multi-tenant shell host. No kernel exploit required; this is pure userland.
Conditions required:
  • Local code execution as any UID with write access to a directory a root process will traverse
Where this breaks in practice:
  • Single-tenant servers with no interactive users have effectively zero exposure
  • Modern hardened CI runners are ephemeral and isolated per job
Detection/coverage: auditd execve of unprivileged shells in unusual locations; EDR process-tree anomalies
STEP 02

Identify a root-run setfattr/getfattr against an attacker-influenced path

The attacker must locate or induce a privileged invocation of setfattr/getfattr operating inside a directory they control. Realistic vectors: backup tools (star, bsdtar, rsync --xattrs, Bareos/Bacula restores) calling the CLIs during restore; container build tooling (buildah, podman build, image extraction in /var/lib/containers/storage); RPM/DEB post-install scripts that touch xattrs on /tmp-staged files; ansible/chef plays managing xattrs on user-owned paths.
Conditions required:
  • A scheduled or triggerable root workflow that invokes attr CLIs on a path the attacker can write within
Where this breaks in practice:
  • Most distros' core packaging does NOT call setfattr/getfattr on attacker-influenced paths during normal operation
  • Backup *restore* operations are rare and usually offline
Detection/coverage: Hard to detect proactively — requires inventorying every cron/systemd/automation pipeline that shells out to attr utilities
STEP 03

Win the TOCTOU race with a symlink swap

Using a tight inotify loop or a directory-rename race (renameat2 + RENAME_EXCHANGE), the attacker swaps a benign file in their controlled directory for a symlink pointing to a target path (e.g., /usr/bin/passwd, /opt/agent/bin/updater) at the precise moment the privileged setfattr walks the path. Public TOCTOU race-window helpers (renameat2 exchange loops, crowbar/symlink-race-pwn-style harnesses) make this a single-digit-attempt exploit on modern kernels.
Conditions required:
  • Attacker can run a long-lived race loop on the target
  • Target kernel supports renameat2 (Linux ≥ 3.15 — universal)
Where this breaks in practice:
  • openat2(RESOLVE_BENEATH) — if any consumer adopted it — neutralizes the race, but attr 2.5.x and earlier do not use it
  • FS-level protected_symlinks (sysctl fs.protected_symlinks=1, default on most distros since 2015) blocks /tmp-style symlink follows for differing UIDs in sticky-bit dirs — significantly raises the bar
Detection/coverage: auditd path records on setfattr execve will show the symlink target post-facto; no real-time prevention
STEP 04

Write security.capability / security.selinux on attacker-chosen binary

On successful race, setfattr -n security.capability -v 0sAQAAAgAgAAAAAAAAAAAAAAAAAAA= /target/binary sets cap_setuid+ep (or any capability) on the redirected target — giving the attacker a SUID-equivalent binary they own conceptually. Alternatively, writing security.selinux flips an enforcing-mode label to a permitted domain.
Conditions required:
  • File system supports security.* xattrs (ext4, xfs, btrfs — yes; tmpfs — varies)
  • Kernel has file capabilities enabled (CONFIG_SECURITY_FILE_CAPABILITIES — universal)
Where this breaks in practice:
  • IMA/EVM appraisal, if enforced, will reject unsigned xattr changes
  • Read-only root or dm-verity (Android, ChromeOS, immutable distros like Fedora Silverblue) prevents the write entirely
Detection/coverage: EDR with file-integrity monitoring on /usr/bin, /usr/sbin, /usr/libexec will flag the xattr change; AIDE/Tripwire baselines catch it on next run
STEP 05

Execute the now-capability-endowed binary → root

Attacker invokes the redirected binary, which now carries cap_setuid (or whatever capability was written) in its file xattrs. Execution drops the attacker into UID 0 or grants the capability scope they need to pivot. Standard post-exploitation follows.
Conditions required:
  • A binary path the attacker can invoke that runs to completion
Where this breaks in practice:
  • EDR behavioral rules flag unexpected setuid syscalls from non-suid binaries
  • Linux Lockdown LSM in 'confidentiality' mode further restricts capability abuse
Detection/coverage: EDR / auditd setuid and capset syscall anomalies
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed as of 2026-06-30. Not in CISA KEV. No GreyNoise tag; this is a local-only primitive so internet telemetry is not the right lens.
Public PoCGeneric symlink-TOCTOU race harnesses (renameat2 exchange loops) work without modification; no CVE-specific public PoC repo published yet at time of writing.
EPSSNot scored at disclosure +1 day; expected <0.5% given local-only AV.
KEV statusNot listed. No CISA action.
CVSS 3.1 vectorAV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N → vendor 7.1 HIGH. Local, low-priv, no user interaction; we re-score 5.3 MEDIUM after race-window and exposure adjustments.
Affected versionsattr < 2.6.0. Ships in essentially every Linux distro (acl/attr is a base dependency of coreutils-adjacent tooling and tar --xattrs).
Fixed versionsUpstream attr 2.6.0 (Savannah attr project). Distro backports expected: Debian/Ubuntu attr security update, RHEL/Alma/Rocky via attr-2.4.48-*.el9_4 backport, SUSE via attr MU, Alpine attr 2.5.x patched-in-place.
Exposure dataNot an internet-reachable surface — Shodan/Censys/FOFA irrelevant. Internal exposure: package is installed on ~100% of Linux hosts but is only *exploitable* on multi-tenant hosts or hosts running root automation against attacker paths (we estimate <5% of typical enterprise fleet).
Disclosure date2026-06-29 (yesterday at time of writing).
ReporterCredited to upstream attr maintainers via Savannah bug tracker; specific researcher attribution pending vendor advisory.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (5.3/10)

Downgraded from vendor HIGH because the decisive factor is the dual prerequisite: the attacker needs an existing local unprivileged shell *and* must race a concurrent root-run invocation of setfattr/getfattr against an attacker-influenced path — a pattern absent from default workloads on single-tenant servers. Multi-tenant shell hosts, shared CI runners, and backup-restore servers remain genuine MEDIUM-grade LPE risk and are where the residual exposure lives.

HIGH Symlink TOCTOU is a real, exploitable class in pre-2.6.0 attr
HIGH Local-only attack vector and PR:L prerequisite
MEDIUM Estimated fleet exposure of multi-tenant / backup-restore hosts (<5%)
LOW Existence of in-the-wild exploitation at this date (none observed)

Why this verdict

  • Local-only vector (AV:L) — there is no remote, unauthenticated path. The attacker must already hold a shell on the target, which collapses the addressable population from 'every Linux box' to 'every multi-tenant Linux box.'
  • Race-window dependency — exploitation requires a *concurrent* privileged invocation of attr CLIs against an attacker-controlled path. On a typical single-tenant application server with no shell users, this condition simply never materializes.
  • Distro defense-in-depthfs.protected_symlinks=1 (default on Debian, Ubuntu, RHEL, SUSE, Alpine, Arch since ~2015) materially raises the cost of the canonical /tmp symlink swap by blocking cross-UID symlink follows in sticky-bit directories. Not a complete fix (does not cover non-sticky attacker-owned dirs), but real friction.
  • Role multiplier — multi-tenant shell hosts / shared CI runners: chain succeeds, blast radius is host-level root → MEDIUM stays MEDIUM, not floored to HIGH because this role is <10% of installed base and the chain remains single-host.
  • Role multiplier — backup/restore servers (Bareos, Bacula, Veeam Linux agent, Commvault): chain plausibly succeeds during restore operations that recreate xattrs against staging dirs; blast radius is host-level root on the backup server, which IS a high-value role. However, restores are rare/operator-initiated, and the attacker needs prior local foothold on the backup server itself. Floor stays at MEDIUM; closely monitor.

Why not higher?

Not HIGH because no remote vector exists, the chain requires the attacker to already be local-authenticated, AND a second prerequisite (concurrent root attr invocation on attacker-influenced path) gates exploitation. On the majority of single-tenant servers, this second prerequisite never occurs. HIGH would be appropriate if the bug were in the kernel xattr layer (universal) or if attr CLIs were routinely invoked by root on /tmp-class paths by default — neither is true.

Why not lower?

Not LOW because the primitive — arbitrary security.capability write — is a clean local privilege escalation when the race lands. On multi-tenant hosts (university, hosting, shared CI, jumpboxes), this is genuinely exploitable and the chain ends in root. The bug also lives in a near-universally installed package, so fleet-wide patching is non-trivial. LOW would understate the LPE potential on the slice of fleet where it matters.

05 · Compensating Control

What to do — in priority order.

  1. Verify fs.protected_symlinks=1 and fs.protected_hardlinks=1 are set fleet-wide — These sysctls have been default-on in mainstream distros since 2015 but configuration drift happens. Enforce via Ansible/Puppet/SCM. This blocks the canonical /tmp symlink-swap variant. Deploy within the noisgate mitigation SLA — no mitigation SLA for MEDIUM, but this is a 10-minute hygiene fix you should do this week regardless.
  2. Inventory and audit root-run invocations of setfattr/getfattr — Grep cron jobs, systemd units, ansible playbooks, container build pipelines, and backup tooling for setfattr, getfattr, tar --xattrs, rsync -X, cp --preserve=xattr. Anywhere root operates on an attacker-influenceable path is a hot spot. Refactor to operate inside private staging directories (mktemp -d with 0700) or behind openat2(RESOLVE_BENEATH) wrappers.
  3. Enable IMA/EVM appraisal on hardened tiers — If you run a Linux integrity baseline (IMA-appraise with EVM-protected xattrs), unauthorized security.capability writes are rejected at the kernel layer. Already deployed? Confirm enforcement is enforce, not log. Realistic for hardened/regulated tiers; impractical for the full fleet inside a 30-day window.
  4. Restrict shell access on application servers — Most enterprise Linux servers should not have interactive non-admin users. Audit /etc/passwd for /bin/bash-shelled UIDs without business justification and convert to /sbin/nologin. Removes the attacker's foothold prerequisite entirely.
  5. Patch to attr 2.6.0 (or distro backport) when available — Track your distro's attr package security advisory. Roll through standard package management — attr is leaf-installed, no service restart required. Within the noisgate remediation SLA of 365 days for MEDIUM; do it during normal monthly patch cycles, no emergency change needed.
What doesn't work
  • Network ACLs / WAF / NGFW — irrelevant, this is a local-only bug with no network surface.
  • EDR signature on the attr binary itself — root *legitimately* runs setfattr/getfattr in many automation flows; signature-blocking creates outage risk without addressing the symlink race.
  • SELinux/AppArmor in targeted/default mode — the attr CLIs are unconfined for root in most distro policies, so MAC does not constrain the xattr write to redirected targets.
  • Removing the attr package — many other packages depend on it transitively (tar, rsync xattr handling, container runtimes); removal will break legitimate workflows.
06 · Verification

Crowdsourced verification payload.

Run on the target Linux host as any user (no privileges required for the version check). Example: ./check-cve-2026-54371.sh. Reports VULNERABLE if installed attr is older than 2.6.0, PATCHED if 2.6.0 or newer, UNKNOWN if getfattr is not present or version parsing fails.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-cve-2026-54371.sh
# Detects vulnerable attr package (< 2.6.0) for CVE-2026-54371.
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN
set -u

FIXED_MAJOR=2
FIXED_MINOR=6
FIXED_PATCH=0

if ! command -v getfattr >/dev/null 2>&1; then
    echo "UNKNOWN: getfattr not installed on this host"
    exit 2
fi

# getfattr --version output: 'getfattr 2.5.1'
RAW="$(getfattr --version 2>/dev/null | head -1 | awk '{print $NF}')"
if [[ -z "$RAW" ]]; then
    echo "UNKNOWN: could not parse getfattr --version"
    exit 2
fi

IFS='.' read -r MAJ MIN PAT <<< "$RAW"
MAJ=${MAJ:-0}; MIN=${MIN:-0}; PAT=${PAT:-0}

# Numeric comparison
if (( MAJ > FIXED_MAJOR )) || \
   { (( MAJ == FIXED_MAJOR )) && (( MIN > FIXED_MINOR )); } || \
   { (( MAJ == FIXED_MAJOR )) && (( MIN == FIXED_MINOR )) && (( PAT >= FIXED_PATCH )); }; then
    echo "PATCHED: attr $RAW (>= 2.6.0)"
    exit 0
fi

# Distro backport check — RHEL/Debian may ship 2.5.x with patch applied
DISTRO_PKG=""
if command -v rpm >/dev/null 2>&1; then
    DISTRO_PKG="$(rpm -q attr 2>/dev/null)"
elif command -v dpkg-query >/dev/null 2>&1; then
    DISTRO_PKG="$(dpkg-query -W -f='${Package} ${Version}\n' attr 2>/dev/null)"
fi

echo "VULNERABLE: attr $RAW (< 2.6.0)"
[[ -n "$DISTRO_PKG" ]] && echo "  Distro package: $DISTRO_PKG (check vendor advisory for backport status)"
echo "  Verify sysctl: $(sysctl -n fs.protected_symlinks 2>/dev/null || echo 'unset') (want: 1)"
exit 1
07 · Bottom Line

If you remember one thing.

TL;DR
Treat this as a MEDIUM local-privilege-escalation issue, not an emergency. Per the noisgate mitigation SLA for MEDIUM there is no mitigation deadline — but this week, push fs.protected_symlinks=1 and fs.protected_hardlinks=1 into your config-management baseline (5-minute change) and grep your automation for root-run setfattr/getfattr against /tmp-class paths. Per the noisgate remediation SLA for MEDIUM, roll the attr 2.6.0 (or distro backport) update through your normal monthly patch cycle within 365 days — no out-of-band change required. Escalate to a 30-day patch window only for multi-tenant shell hosts, shared CI runners, and Linux-side backup/restore servers where the local-attacker prerequisite is realistic.

Sources

  1. Savannah attr project
  2. getfattr(1) man page
  3. setfattr(1) man page
  4. CWE-59: Improper Link Resolution Before File Access ('Link Following')
  5. Linux kernel fs.protected_symlinks documentation
  6. openat2() RESOLVE_BENEATH (Linux 5.6+)
  7. Linux file capabilities (capabilities(7))
  8. CISA KEV catalog
Peer Review

What defenders are saying.

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

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.