← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-41651 · CWE-367 · Disclosed 2026-04-22

PackageKit is a a D-Bus abstraction layer

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a valet ticket swap that lets a low-priv user walk away with the root keys

CVE-2026-41651 is a local privilege escalation in packagekitd, the root-running D-Bus service behind PackageKit. A low-privileged local user can queue an allowed transaction, then overwrite its flags and payload before execution so the daemon installs attacker-controlled packages as root; package scriptlets then deliver full root execution. Upstream says versions >= 1.0.2 and <= 1.3.4 are confirmed vulnerable, with likely exposure back to 0.8.1; the upstream fix is 1.3.5, and major distros shipped backports.

The vendor's HIGH 8.8 is technically fair, but operationally this is not a CRITICAL fire drill because it requires an existing local foothold (AV:L/PR:L). That prerequisite matters: on a 10,000-host estate this is a post-initial-access privilege escalator, not an entry vector. What keeps it in HIGH instead of dropping further is that exploitation is reliable, fast, publicly weaponized, and root-complete on default installs across multiple distros.

"Dangerous and reliable, but still a post-compromise local root bug—not an internet-breaker."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Land a low-priv shell

The attacker first needs code execution or an interactive session as a non-root user on the target Linux host. In practice that means SSH with stolen creds, desktop malware, a webapp-to-shell chain, or another local user context. Weaponized stage: any initial-access implant or shell; this CVE is the privilege-escalation follow-on, not the opener.
Conditions required:
  • Attacker has local code execution or a valid low-priv account
  • Target is Linux with PackageKit installed
Where this breaks in practice:
  • No remote unauthenticated path into packagekitd
  • This assumes the attacker already beat your initial-access controls
Detection/coverage: EDR and auth telemetry can catch the foothold stage, but vulnerability scanners often miss the practical risk if they only key on externally reachable services.
STEP 02

Reach PackageKit over system D-Bus

The exploit talks to packagekitd over the system bus, typically with D-Bus client calls that mirror InstallFiles() behavior. Because PackageKit can be D-Bus activated, the daemon may not appear persistently in a process list even when exploitable. Weaponized tooling: public PoCs such as Vozec/CVE-2026-41651 or custom gdbus/libdbus clients.
Conditions required:
  • PackageKit is installed
  • System D-Bus service is available
  • Policy allows the initial 'safe' transaction path
Where this breaks in practice:
  • Some servers do not install PackageKit at all
  • Minimal images and hardened server builds often remove PackageKit/Cockpit integration
Detection/coverage: Asset inventory beats network scanning here. Check installed packagekit packages and whether packagekit.service is loaded or D-Bus activatable.
STEP 03

Queue a 'safe' transaction

The attacker creates a transaction and submits an InstallFiles() call with flags such as SIMULATE, which PackageKit treats as non-destructive and therefore skips polkit authorization for. This moves the transaction into a state that will later be executed by the scheduler. Weaponized step: the PoC's first async D-Bus call.
Conditions required:
  • Vulnerable PackageKit transaction handling
  • Attacker can submit D-Bus method calls as an unprivileged user
Where this breaks in practice:
  • If PackageKit package-install actions are denied outright by local polkit policy, this chain breaks early
  • Hosts without PackageKit package installation features exposed are not affected
Detection/coverage: D-Bus tracing or audit rules can see PackageKit method calls, but most enterprise EDR stacks do not decode this path well by default.
STEP 04

Overwrite flags before dispatch

The attacker immediately sends a second InstallFiles() call on the same transaction with real install flags and an attacker-controlled package path. The bug chain matters here: PackageKit overwrites cached flags unconditionally, silently rejects the backward state transition, and later reads the overwritten flags at execution time. Telekom's write-up notes GLib main-loop ordering makes this deterministic rather than a flaky race. Weaponized step: the PoC's second async D-Bus call.
Conditions required:
  • Same transaction can be reused before idle callback execution
  • Daemon is running an unpatched transaction state machine
Where this breaks in practice:
  • Patched versions or distro backports remove the overwrite path
  • Aggressive host hardening that disables PackageKit package installs for non-root users blocks abuse
Detection/coverage: Look for PackageKit crashes and assertion failures after exploitation attempts; vendor research gives a strong log IOC.
STEP 05

Run package scriptlets as root

The backend performs a real package install as root, and the attacker's package postinst/RPM scriptlet executes arbitrary commands to drop a SUID shell, add sudoers entries, or implant persistence. At that point the attacker owns the box. Weaponized tooling: crafted .deb/.rpm payload package from public PoCs.
Conditions required:
  • Attacker can place a malicious package file locally
  • Backend install path is reached before polkit denial matters
Where this breaks in practice:
  • Some MAC policies or filesystem controls may block the post-exploitation payload choice
  • This is single-host privilege escalation, not domain-wide by itself
Detection/coverage: Check journalctl -u packagekit for assertion failures like the emitted_finished crash pattern, plus package install history and sudden SUID file creation.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo confirmed KEV listing and no authoritative public in-the-wild campaign evidence found as of 2026-05-31. This is an inference from current public sources plus the user's intel block, not a claim of absence forever.
PoC availabilityPublic exploit code exists. Telekom's timeline says a GitHub exploit appeared on 2026-04-23, and live repos such as Vozec/CVE-2026-41651 show working weaponization.
EPSS0.00153 from the user's intel block. That's low, which fits a non-remote LPE, but EPSS routinely underweights post-compromise privilege escalators that operators use after access is already gained.
KEV statusNot KEV-listed per the user's intel block; no corresponding entry was found in CISA's current KEV catalog view.
CVSS vector reality checkCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H correctly says easy local root. The operational downgrade pressure is entirely in AV:L/PR:L: attacker must already be on the box.
Affected versionsUpstream GHSA says affected >= 0.8.1 and <= 1.3.4, with confirmed vulnerable >= 1.0.2 and <= 1.3.4. Tested by the vendor researchers on Ubuntu, Debian, Rocky Linux, and Fedora default installs.
Fixed versionsUpstream fixed in 1.3.5. Notable distro backports: Debian bullseye 1.2.2-2+deb11u1, bookworm 1.2.6-5+deb12u1, trixie 1.3.1-1+deb13u1; Ubuntu noble 1.2.8-2ubuntu1.5, jammy 1.2.5-2ubuntu3.1, focal 1.1.13-2ubuntu1.1+esm1; Fedora 42-44 1.3.4-3 per Telekom.
Exposure and scanningNo meaningful Shodan/Censys-style internet exposure signal. packagekitd is a local D-Bus service, often D-Bus activated, so external attack-surface tools will undercount or miss it entirely. The real exposure question is where PackageKit is installed, especially desktops and Cockpit-enabled servers.
Disclosure timelinePublic disclosure and upstream fix landed on 2026-04-22. Telekom's timeline says private report 2026-04-08, distros notified by 2026-04-19, and public GitHub exploit available 2026-04-23.
Reporter / research orgReported by Deutsche Telekom Red Team; GHSA credits reporter msatdt and remediation developer ximion.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (7.6/10)

The single biggest factor is attacker position: this flaw requires an already-established local low-privileged foothold, which makes it a post-compromise escalator, not an initial-access event. It stays HIGH because once that foothold exists, the exploit path is reliable, publicly available, and ends in immediate full-root compromise on the host.

HIGH Exploitability on vulnerable hosts
MEDIUM Prevalence across enterprise Linux server fleets

Why this verdict

  • Local authenticated foothold required — score down from 8.8. AV:L/PR:L means the attacker must already have shell/code execution or a valid unprivileged account on the host, so this is not a perimeter-breaking bug.
  • Exploit reliability and public weaponization — score back up. Telekom describes the GLib event ordering that makes the race dependable, and public GitHub PoCs remove most engineering work for post-compromise operators.
  • Wide install base, but not universal and not internet-facing. PackageKit is common on desktops and present on some servers via Cockpit, yet plenty of hardened or minimal server images do not ship it, which trims the reachable population.

Why not higher?

This is not higher because there is no unauthenticated remote path and no credible public evidence that it is being broadly exploited in the wild right now. The exploit chain begins only after another control has already failed and the attacker is executing locally as a normal user.

Why not lower?

This is not lower because the impact is full root, the exploit is fast and deterministic, and tested-default-install coverage spans multiple mainstream distros. For shared Linux systems, developer workstations, VDI, jump hosts, and Cockpit-managed servers, this is exactly the kind of LPE operators use to turn a nuisance foothold into a real incident.

05 · Compensating Control

What to do — in priority order.

  1. Patch PackageKit or deploy distro backports — Make the package update the primary control and complete it within 180 days for the HIGH verdict, faster on multi-user Linux systems. Where patch rollout is lagging, use the distro-provided backport rather than waiting for upstream 1.3.5 exactly.
  2. Deny PackageKit install actions for non-root users — If you cannot patch promptly, deploy the vendor-recommended polkit rule to block PackageKit package-install actions for non-root users within 30 days. This directly cuts the exploit chain at the authorization boundary and is the best compensating control for exposed-but-unpatched hosts.
  3. Remove or mask PackageKit on servers that do not need it — On server roles where GUI software management is irrelevant, uninstall PackageKit or mask/disable the service path within 30 days. This shrinks your reachable population and is especially useful on Cockpit-enabled or admin utility images.
  4. Hunt for PackageKit assertion crashes — Search journalctl -u packagekit and central log stores for the PackageKit assertion-failure IOC described by Telekom within 30 days and keep the detection in place until remediation is complete. Successful exploitation tends to leave a noisy daemon crash trail even though systemd recovers the service.
  5. Prioritize user-accessible Linux hosts — Sequence your estate so shared desktops, dev workstations, bastions, teaching/research clusters, and any host where non-admin users can run code get attention first within 30 days. The business risk is highest where many low-privileged users can touch the box.
What doesn't work
  • A WAF or perimeter IPS does nothing here because the vulnerable path is local D-Bus traffic, not an exposed HTTP service.
  • Checking only the running process list is weak coverage because PackageKit may be D-Bus activated and absent until invoked.
  • MFA helps protect initial access but does not stop abuse once an attacker already has a local user context on the host.
  • Hardening sudo alone does not help because the exploit bypasses normal admin elevation flow and runs package scriptlets as root through PackageKit.
06 · Verification

Crowdsourced verification payload.

Run this on the target Linux host, not from a remote scanner. Invoke it as bash ./check-packagekit-cve-2026-41651.sh; no root is strictly required for package-version checks, but root helps if you also want to validate service status and logs. The script prints VULNERABLE, PATCHED, or UNKNOWN and exits 0, 1, or 2 respectively.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-packagekit-cve-2026-41651.sh
# Detect likely exposure to CVE-2026-41651 on Debian/Ubuntu/RPM-based Linux hosts.
# Exit codes: 0=PATCHED/NOT INSTALLED, 1=VULNERABLE, 2=UNKNOWN

set -u

CVE="CVE-2026-41651"
OS_ID="unknown"
OS_VER="unknown"
INSTALLED_VER=""

if [[ -r /etc/os-release ]]; then
  # shellcheck disable=SC1091
  . /etc/os-release
  OS_ID="${ID:-unknown}"
  OS_VER="${VERSION_ID:-unknown}"
fi

say() { echo "$1"; }
fail_unknown() { say "UNKNOWN: $1"; exit 2; }
fail_vuln() { say "VULNERABLE: $1"; exit 1; }
pass_patch() { say "PATCHED: $1"; exit 0; }

check_dpkg() {
  if ! command -v dpkg-query >/dev/null 2>&1; then
    return 1
  fi

  if ! dpkg-query -W -f='${Status} ${Version}\n' packagekit 2>/dev/null | grep -q '^install ok installed '; then
    pass_patch "packagekit not installed"
  fi

  INSTALLED_VER="$(dpkg-query -W -f='${Version}' packagekit 2>/dev/null)"
  [[ -n "$INSTALLED_VER" ]] || fail_unknown "packagekit installed but version could not be read"

  FIXED=""
  case "$OS_ID:$OS_VER" in
    ubuntu:24.04) FIXED='1.2.8-2ubuntu1.5' ;;
    ubuntu:22.04) FIXED='1.2.5-2ubuntu3.1' ;;
    ubuntu:20.04) FIXED='1.1.13-2ubuntu1.1+esm1' ;;
    ubuntu:18.04) FIXED='1.1.9-1ubuntu2.18.04.6+esm1' ;;
    ubuntu:16.04) FIXED='0.8.17-4ubuntu6~gcc5.4ubuntu1.5+esm1' ;;
    debian:11) FIXED='1.2.2-2+deb11u1' ;;
    debian:12) FIXED='1.2.6-5+deb12u1' ;;
    debian:13) FIXED='1.3.1-1+deb13u1' ;;
  esac

  if [[ -n "$FIXED" ]]; then
    if dpkg --compare-versions "$INSTALLED_VER" ge "$FIXED"; then
      pass_patch "packagekit $INSTALLED_VER on $OS_ID $OS_VER is at or above fixed distro version $FIXED"
    else
      fail_vuln "packagekit $INSTALLED_VER on $OS_ID $OS_VER is below fixed distro version $FIXED"
    fi
  fi

  if dpkg --compare-versions "$INSTALLED_VER" ge '1.3.5'; then
    pass_patch "packagekit $INSTALLED_VER is at or above upstream fixed version 1.3.5"
  fi

  if dpkg --compare-versions "$INSTALLED_VER" ge '1.0.2' && dpkg --compare-versions "$INSTALLED_VER" le '1.3.4'; then
    fail_vuln "packagekit $INSTALLED_VER falls in confirmed vulnerable upstream range 1.0.2-1.3.4"
  fi

  fail_unknown "packagekit $INSTALLED_VER could not be mapped confidently to a fixed or vulnerable state"
}

check_rpm() {
  if ! command -v rpm >/dev/null 2>&1; then
    return 1
  fi

  if ! rpm -q PackageKit >/dev/null 2>&1; then
    pass_patch "PackageKit not installed"
  fi

  INSTALLED_VER="$(rpm -q --qf '%{VERSION}-%{RELEASE}\n' PackageKit 2>/dev/null)"
  [[ -n "$INSTALLED_VER" ]] || fail_unknown "PackageKit installed but version could not be read"

  ver_ge() {
    local a="$1" b="$2"
    [[ "$(printf '%s\n%s\n' "$a" "$b" | sort -V | tail -n1)" == "$a" ]]
  }

  ver_le() {
    local a="$1" b="$2"
    [[ "$(printf '%s\n%s\n' "$a" "$b" | sort -V | head -n1)" == "$a" ]]
  }

  case "$OS_ID" in
    fedora)
      if ver_ge "$INSTALLED_VER" '1.3.4-3'; then
        pass_patch "PackageKit $INSTALLED_VER on Fedora is at or above known fixed build 1.3.4-3"
      fi
      ;;
    rhel|rocky|almalinux|centos)
      if [[ "$OS_VER" == 9* ]] && ver_ge "$INSTALLED_VER" '1.2.6-1.el9_4.1'; then
        pass_patch "PackageKit $INSTALLED_VER on EL9 is at or above known fixed build 1.2.6-1.el9_4.1"
      fi
      ;;
  esac

  if ver_ge "$INSTALLED_VER" '1.3.5'; then
    pass_patch "PackageKit $INSTALLED_VER is at or above upstream fixed version 1.3.5"
  fi

  if ver_ge "$INSTALLED_VER" '1.0.2' && ver_le "$INSTALLED_VER" '1.3.4'; then
    fail_vuln "PackageKit $INSTALLED_VER falls in confirmed vulnerable upstream range 1.0.2-1.3.4"
  fi

  fail_unknown "PackageKit $INSTALLED_VER could not be mapped confidently to a fixed or vulnerable RPM build"
}

check_dpkg || true
check_rpm || true
fail_unknown "unsupported package manager or unable to determine PackageKit installation state for $CVE"
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, inventory every Linux host with PackageKit installed, then split the queue: first shared-user systems, desktops, bastions, developer workstations, and Cockpit-managed servers; second everything else. For this HIGH call, the noisgate mitigation SLA is within 30 days: if patching is not immediate, deploy the polkit deny rule or remove/disable PackageKit where it is unnecessary. The noisgate remediation SLA is within 180 days: roll the actual distro patch/backport across the fleet, but do the user-accessible Linux population first because this bug turns any ordinary foothold into root with very little drama.

Sources

  1. GitHub Security Advisory GHSA-f55j-vvr9-69xv
  2. Openwall oss-security disclosure
  3. Telekom Security research write-up
  4. Ubuntu CVE page
  5. Debian security tracker
  6. NVD record
  7. Public PoC repository
  8. CISA Known Exploited Vulnerabilities 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.