This is a janitor’s key that only opens one side door in one building layout
CVE-2026-4948 is a local firewalld mis-authorization flaw in the D-Bus setters setZoneSettings2 and setPolicySettings. In vulnerable builds, those setters are protected with PK_ACTION_CONFIG_INFO instead of PK_ACTION_CONFIG, which matters because the shipped desktop polkit profile allows configuration *inspection* without authentication. Upstream, the bug affects firewalld <= 2.4.0; the fix lands in v2.4.1. Debian shows backported fixes in 0.9.3-2+deb11u1 for bullseye and 2.3.1-1+deb13u1 for trixie, while SUSE ships fixed package builds such as firewalld >= 1.3.4-150600.13.6.1 on SLES 15 SP6/SP7.
The vendor’s MEDIUM 5.5 rating is technically fair in a lab, but it is too generous for enterprise patch triage. Real-world exploitation requires local unprivileged code execution or shell access first, then a host that actually uses the desktop policy profile, and the outcome is runtime firewall-state tampering on that one host, not remote takeover. That is classic post-initial-access friction, so this gets downgraded to LOW.
4 steps from start to impact.
Land on the box first
- Local unprivileged access to the Linux host
- firewalld installed and running
- This is post-compromise by definition
- Many enterprise Linux systems are headless servers, not interactive multi-user desktops
Find a host with the desktop polkit profile
config.info-style operations without authentication. The upstream fix changes the setters to require PK_ACTION_CONFIG, closing the gap.- A vulnerable firewalld build
- Desktop polkit policy installed/active for Firewalld
- Server-oriented deployments typically do not rely on the desktop policy path
- Backported distro fixes mean package version alone may mislead
Call the mis-authorized D-Bus methods
busctl, gdbus, or a small Python D-Bus client, the attacker invokes setZoneSettings2 or setPolicySettings. Because those setters were wrongly guarded with the weaker auth action, firewalld accepts runtime policy changes that should have required admin authentication.- Access to the system bus
- Knowledge of firewalld D-Bus method signatures
- The attacker still needs working local execution and D-Bus access
- The bug changes runtime state, so the impact is immediate but not necessarily persistent
busctl/gdbus access to org.fedoraproject.FirewallD1; off-the-shelf scanners rarely validate this path.Punch a temporary hole in host filtering
- A useful firewall rule change exists for the attacker’s objective
- Target workload depends on firewalld for host-level filtering
- Impact is bounded to the affected host
- Runtime-only changes may disappear on reload/restart or be overwritten by config management
firewall-cmd --list-all-zones and --runtime-to-permanent drift, review journald firewalld events, and alert on unexpected runtime policy churn.The supporting signals.
| In-the-wild status | No known active exploitation in primary sources reviewed. OpenCVE surfaces CISA ADP enrichment marking Exploitation: none; the user-provided KEV status is also No. |
|---|---|
| Proof-of-concept availability | No standalone exploit repo found in primary-source review. The public fix commit is enough for a competent operator to build a trivial busctl/gdbus abuse once local access exists. |
| EPSS | 0.00027 from the supplied intel — effectively near-zero exploit probability in fleet terms. Third-party mirrors place it around ~0.02% and roughly ~P5 percentile, but treat the percentile as low-confidence. |
| KEV status | Not KEV-listed. No CISA Known Exploited Vulnerabilities entry was found for this CVE in the reviewed catalog sources. |
| CVSS meaning | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N means local, low-complexity, low-privilege, no user interaction, with integrity impact only. That already tells you this is post-foothold. |
| Affected versions | Primary-source tracking says upstream firewalld <= 2.4.0 is affected. Red Hat CNA data explicitly marks RHEL 7 affected and leaves RHEL 8/9/10 and OpenShift 4 as unknown in the CNA record rather than broadly declaring them vulnerable. |
| Fixed versions | Upstream fix is firewalld v2.4.1. Debian lists fixed builds in bullseye 0.9.3-2+deb11u1, trixie 2.3.1-1+deb13u1, and unstable 2.4.0-2; SUSE lists fixed packages including firewalld >= 1.3.4-150600.13.6.1 on SLES 15 SP6/SP7. |
| Exposure population | Not internet-scannable in any meaningful way. This is a local D-Bus/polkit authorization flaw, so Shodan/Censys/FOFA style exposure counts do not map to attacker reachability. |
| Disclosure | Publicly disclosed 2026-03-27. NVD shows publication on 2026-03-27 and last modification on 2026-05-15. |
| Reporter | Reported by Asim Viladi Oglu Manizada per the CNA record exposed through OpenCVE. |
noisgate verdict.
The decisive factor is attacker position: this bug starts at local unprivileged access, which means the adversary is already on the host before the flaw matters. The second major suppressor is reachability: exploitation additionally depends on the desktop polkit profile, which sharply narrows the real exposed population in enterprise Linux fleets.
Why this verdict
- Downward adjustment: requires local unprivileged access first — this is not an initial-access bug, not a perimeter bug, and not something an unauthenticated remote attacker can hit.
- Downward adjustment: desktop policy prerequisite narrows the blast radius — the exploitable path depends on the shipped desktop polkit profile being present/active, which is not how most headless Linux servers are run.
- Downward adjustment: impact is host-local and runtime-scoped — the attacker can tamper with the running firewall state on one machine, but this is not code execution and not an immediate fleet-wide persistence mechanism.
Why not higher?
If this were remotely reachable, unauthenticated, or broadly exposed across server fleets, the integrity impact to firewall policy would justify a much higher rating. But the chain is gated by local access first and then by a specific desktop authorization profile, which strips away most of the theoretical severity.
Why not lower?
It is still a real authorization flaw in a security control, not bookkeeping noise. On shared Linux workstations, developer boxes, VDI-style Linux desktops, or jump hosts where firewalld meaningfully segments traffic, an unprivileged user can weaken host filtering immediately and aid lateral movement.
What to do — in priority order.
- Audit for desktop Firewalld polkit policy — Identify hosts carrying the desktop Firewalld policy file and prioritize them over generic firewalld installs. For a LOW verdict there is no SLA — treat as backlog hygiene, but this is the fastest way to separate truly exposed endpoints from noise.
- Remove or replace the desktop policy on shared systems — On multi-user Linux workstations and jump hosts, prefer the stricter server-style policy or remove unneeded GUI management components so
config.infois not enough to reach sensitive runtime setters. For LOW, there is no SLA — treat as backlog hygiene and bundle this into desktop hardening baselines. - Watch for runtime firewall drift — Alert on unexpected
firewall-cmd,busctl,gdbus, and direct D-Bus access toorg.fedoraproject.FirewallD1, then compare runtime vs permanent rules. For LOW, there is no SLA — treat as backlog hygiene, but it is a useful detective control on admin workstations and shared Linux hosts. - Reduce local foothold opportunities — This vulnerability only matters after a local foothold, so hardening SSH, PAM, sudo, browser isolation, and endpoint controls cuts the only realistic entry path. For LOW, there is no SLA — treat as backlog hygiene.
- A perimeter WAF or external IPS does nothing here because there is no direct network-reachable exploit surface.
- Blind package-version reporting does not reliably tell you exploitable state because distro backports and the desktop-policy prerequisite both matter.
- MFA does not stop the vulnerable D-Bus method once the attacker already has local code execution under a normal user context.
Crowdsourced verification payload.
Run this on the target Linux host, not from a scanner workstation. Save it as check-cve-2026-4948.sh and execute sudo bash check-cve-2026-4948.sh; root is preferred so the script can inspect installed firewalld Python sources and polkit action files without path/permission surprises.
#!/usr/bin/env bash
# check-cve-2026-4948.sh
# Detects likely exploitable state for CVE-2026-4948.
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
set -u
status="UNKNOWN"
reason=""
find_firewalld_py() {
local candidates=(
/usr/lib*/python*/site-packages/firewall/server/firewalld.py
/usr/lib*/python*/dist-packages/firewall/server/firewalld.py
/usr/lib/firewalld/firewalld.py
)
local f
for pattern in "${candidates[@]}"; do
for f in $pattern; do
[ -f "$f" ] && { echo "$f"; return 0; }
done
done
return 1
}
has_vuln_decorator() {
local file="$1"
python3 - "$file" <<'PY'
import sys
path = sys.argv[1]
with open(path, 'r', encoding='utf-8', errors='ignore') as fh:
lines = fh.readlines()
def prev_nonempty(idx):
j = idx - 1
while j >= 0:
s = lines[j].strip()
if s:
return s
j -= 1
return ""
z = False
p = False
for i, line in enumerate(lines):
s = line.strip()
if s.startswith('def setZoneSettings2('):
z = 'PK_ACTION_CONFIG_INFO' in prev_nonempty(i)
if s.startswith('def setPolicySettings('):
p = 'PK_ACTION_CONFIG_INFO' in prev_nonempty(i)
if z and p:
print('VULN')
sys.exit(0)
else:
print('PATCHED_OR_UNKNOWN')
sys.exit(1)
PY
}
has_desktop_policy() {
local dir file
for dir in /usr/share/polkit-1/actions /etc/polkit-1/actions; do
[ -d "$dir" ] || continue
while IFS= read -r -d '' file; do
if grep -q 'org.fedoraproject.FirewallD1.config.info' "$file" 2>/dev/null && \
grep -q 'org.fedoraproject.FirewallD1.policies.info' "$file" 2>/dev/null && \
grep -q '<allow_active>yes</allow_active>' "$file" 2>/dev/null; then
echo "$file"
return 0
fi
done < <(find "$dir" -maxdepth 1 -type f -name '*FirewallD*.policy' -print0 2>/dev/null)
done
return 1
}
firewalld_py="$(find_firewalld_py 2>/dev/null || true)"
if [ -z "$firewalld_py" ]; then
echo "UNKNOWN - could not locate installed firewalld Python service file"
exit 2
fi
if has_vuln_decorator "$firewalld_py" >/dev/null 2>&1; then
desktop_policy="$(has_desktop_policy 2>/dev/null || true)"
if [ -n "$desktop_policy" ]; then
echo "VULNERABLE - vulnerable setters found in $firewalld_py and desktop polkit policy present at $desktop_policy"
exit 1
else
echo "UNKNOWN - vulnerable setters found in $firewalld_py but no desktop polkit policy detected; prerequisite may be absent"
exit 2
fi
else
echo "PATCHED - vulnerable setter decorators not detected in $firewalld_py"
exit 0
fi
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.