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.
5 steps from start to impact.
Establish local foothold as unprivileged user
- Local code execution as any UID with write access to a directory a root process will traverse
- Single-tenant servers with no interactive users have effectively zero exposure
- Modern hardened CI runners are ephemeral and isolated per job
execve of unprivileged shells in unusual locations; EDR process-tree anomaliesIdentify a root-run setfattr/getfattr against an attacker-influenced path
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.- A scheduled or triggerable root workflow that invokes attr CLIs on a path the attacker can write within
- Most distros' core packaging does NOT call setfattr/getfattr on attacker-influenced paths during normal operation
- Backup *restore* operations are rare and usually offline
Win the TOCTOU race with a symlink swap
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.- Attacker can run a long-lived race loop on the target
- Target kernel supports
renameat2(Linux ≥ 3.15 — universal)
- 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(sysctlfs.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
path records on setfattr execve will show the symlink target post-facto; no real-time preventionWrite security.capability / security.selinux on attacker-chosen binary
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.- File system supports
security.*xattrs (ext4, xfs, btrfs — yes; tmpfs — varies) - Kernel has file capabilities enabled (CONFIG_SECURITY_FILE_CAPABILITIES — universal)
- 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
/usr/bin, /usr/sbin, /usr/libexec will flag the xattr change; AIDE/Tripwire baselines catch it on next runExecute the now-capability-endowed binary → root
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.- A binary path the attacker can invoke that runs to completion
- EDR behavioral rules flag unexpected setuid syscalls from non-suid binaries
- Linux Lockdown LSM in 'confidentiality' mode further restricts capability abuse
setuid and capset syscall anomaliesThe supporting signals.
| In-the-wild exploitation | None 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 PoC | Generic symlink-TOCTOU race harnesses (renameat2 exchange loops) work without modification; no CVE-specific public PoC repo published yet at time of writing. |
| EPSS | Not scored at disclosure +1 day; expected <0.5% given local-only AV. |
| KEV status | Not listed. No CISA action. |
| CVSS 3.1 vector | AV: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 versions | attr < 2.6.0. Ships in essentially every Linux distro (acl/attr is a base dependency of coreutils-adjacent tooling and tar --xattrs). |
| Fixed versions | Upstream 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 data | Not 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 date | 2026-06-29 (yesterday at time of writing). |
| Reporter | Credited to upstream attr maintainers via Savannah bug tracker; specific researcher attribution pending vendor advisory. |
noisgate verdict.
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.
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-depth —
fs.protected_symlinks=1(default on Debian, Ubuntu, RHEL, SUSE, Alpine, Arch since ~2015) materially raises the cost of the canonical/tmpsymlink 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.
What to do — in priority order.
- Verify
fs.protected_symlinks=1andfs.protected_hardlinks=1are 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/tmpsymlink-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. - 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 -dwith 0700) or behindopenat2(RESOLVE_BENEATH)wrappers. - Enable IMA/EVM appraisal on hardened tiers — If you run a Linux integrity baseline (IMA-appraise with EVM-protected xattrs), unauthorized
security.capabilitywrites are rejected at the kernel layer. Already deployed? Confirm enforcement isenforce, notlog. Realistic for hardened/regulated tiers; impractical for the full fleet inside a 30-day window. - Restrict shell access on application servers — Most enterprise Linux servers should not have interactive non-admin users. Audit
/etc/passwdfor/bin/bash-shelled UIDs without business justification and convert to/sbin/nologin. Removes the attacker's foothold prerequisite entirely. - Patch to attr 2.6.0 (or distro backport) when available — Track your distro's
attrpackage security advisory. Roll through standard package management —attris 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.
- Network ACLs / WAF / NGFW — irrelevant, this is a local-only bug with no network surface.
- EDR signature on the
attrbinary 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
attrpackage — many other packages depend on it transitively (tar, rsync xattr handling, container runtimes); removal will break legitimate workflows.
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.
#!/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
If you remember one thing.
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
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.