Apr 22, 2026·6 min read·12 visits
A TOCTOU race condition in PackageKit's transaction handling allows unprivileged local users to bypass Polkit authorization. Attackers can leverage this to install arbitrary malicious packages as root, leading to complete system compromise. Organizations must update PackageKit to version 1.3.5.
CVE-2026-41651, internally tracked as Pack2TheRoot, is a high-severity local privilege escalation vulnerability in the PackageKit daemon (packagekitd). The flaw involves a Time-of-Check Time-of-Use (TOCTOU) race condition in D-Bus transaction handling that permits local unprivileged users to bypass Polkit authorization and install arbitrary packages as root.
PackageKit operates as a D-Bus abstraction layer designed to facilitate software installation and updates across diverse Linux distributions. The daemon component, packagekitd, manages package management transactions and delegates authorization decisions to Polkit. This architecture separates the user-facing interface from the privileged execution backend.
CVE-2026-41651 represents a Time-of-Check Time-of-Use (TOCTOU) race condition, categorized under CWE-367. The vulnerability resides specifically within the transaction state machine implemented in src/pk-transaction.c. The daemon fails to lock transaction properties securely between the authorization phase and the execution phase.
The resulting impact is a local privilege escalation capability. An attacker bypasses the Polkit authorization constraints entirely, forcing the system to execute unauthorized package installations. Unprivileged users leverage this defect to deploy malicious RPM payloads, achieving arbitrary code execution with root privileges.
Default installations of several major Linux distributions contain the vulnerable PackageKit configuration. The confirmed affected systems include Ubuntu Desktop (18.04, 24.04.4, 26.04), Ubuntu Server, Debian Trixie 13.4, RockyLinux Desktop 10.1, Fedora 43, and Red Hat Enterprise Linux instances utilizing Cockpit.
The vulnerability stems from three distinct architectural failures within src/pk-transaction.c. The first failure is an unconditional flag overwrite mechanism. The InstallFiles() method, alongside other action methods, writes user-supplied transaction flags directly to transaction->cached_transaction_flags. The code fails to enforce a check verifying whether the transaction is already authorized or in a RUNNING state before accepting memory modifications.
The second failure involves a silent state-machine guard located between lines 873 and 882. The function pk_transaction_set_state() intercepts backward state transitions, such as an attempt to transition from RUNNING back to WAITING_FOR_AUTH. The function drops the invalid state transition silently but permits the primary execution thread to proceed. This allows the attacker to alter flags without aborting the broader transaction lifecycle.
The third failure is the late flag read implementation within the PackageKit scheduler. The scheduler schedules transactions using an idle callback routine. This callback reads the cached_transaction_flags at the exact moment of execution dispatch (lines 2273-2277). The callback does not utilize the state values present at the time Polkit granted authorization.
Combining these three flaws generates a persistent desynchronization between authorization and execution. The Polkit engine validates one set of flags during the authorization check, while the package management backend executes an entirely different set of attacker-controlled flags read during dispatch.
Prior to version 1.3.5, the D-Bus method handlers lacked state validation at the functional entry point. The application permitted sequential D-Bus calls targeting the same transaction object. This architectural oversight provided the primitive required to mutate transaction variables post-authorization.
The patch introduced in commit 76cfb675fb31acc3ad5595d4380bfff56d2a8697 resolves the vulnerability by enforcing a strict boundary check. The update restricts all action methods to transactions residing explicitly in the PK_TRANSACTION_STATE_NEW state. Any invocation against a transaction in a later state produces an immediate error.
The implementation of the fix within src/pk-transaction.c is straightforward and structurally blocks the TOCTOU attack vector:
if (transaction->state != PK_TRANSACTION_STATE_NEW) {
g_dbus_method_invocation_return_error (invocation,
PK_TRANSACTION_ERROR,
PK_TRANSACTION_ERROR_INVALID_STATE,
"cannot call %s on transaction %s: already in state %s",
method_name, transaction->tid,
pk_transaction_state_to_string (transaction->state));
return;
}This remediation strategy is complete regarding the specific race condition vector. By halting subsequent method calls on the same transaction identifier, the logic denies an attacker the ability to invoke the unconditional flag overwrite mechanism. The transaction state machine now accurately synchronizes the authorization phase with the execution phase.
The exploitation process requires the attacker to execute precise D-Bus interactions against the packagekitd service. The attacker initiates a legitimate package management transaction requesting an action requiring authorization. They provide benign transaction flags, such as configuring ONLY_TRUSTED to TRUE, to ensure the Polkit framework grants authorization without prompting for root credentials.
Immediately following authorization, the attacker triggers the TOCTOU race condition. Before the scheduler's idle callback dispatches the operation, the attacker invokes InstallFiles() a second time targeting the exact same transaction object. The attacker supplies malicious flags during this secondary invocation, altering parameters like ONLY_TRUSTED to FALSE.
The daemon processes the secondary invocation and overwrites the internal memory state. The silent state-machine guard ignores the invalid state transition attempt but allows the flag overwrite instruction to succeed. The malicious flags replace the authorized flags in memory.
The execution phase commences when the PackageKit scheduler fires the idle callback. The scheduler reads the recently injected malicious flags and passes them directly to the underlying package manager backend. The backend processes the attacker-supplied RPM payload and executes any embedded scriptlets with elevated root privileges.
Successful exploitation of CVE-2026-41651 results in complete system compromise. The vulnerability grants a local unprivileged user the capability to execute arbitrary code with root privileges. The attacker bypasses intended security controls and achieves absolute control over the target system.
The CVSS v3.1 vector is evaluated as CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H, producing a score of 8.8. The attack vector requires local system access (AV:L) and low-level privileges (PR:L). The exploitation mechanics operate independently of user interaction (UI:N) and impact the broader host environment directly (S:C). Confidentiality, integrity, and availability all suffer high impacts.
Enterprise environments utilizing Linux desktop systems or management consoles like Cockpit face immediate operational risk. These platforms often deploy PackageKit by default to streamline software maintenance. Attackers possessing shell access can utilize this vulnerability to establish persistent backdoors via rogue package deployments.
Failed exploitation attempts generate specific system indicators. Exploitation instability often forces the packagekitd process to crash. System administrators reviewing journalctl logs will observe assertion failures originating from pk_transaction_finished_emit.
The definitive remediation for CVE-2026-41651 requires upgrading the PackageKit installation to version 1.3.5 or later. Administrators must deploy the updated packages provided by their respective distribution vendors. Restarting the packagekitd service or rebooting the host ensures the patched daemon replaces the vulnerable memory instance.
Organizations incapable of deploying immediate software updates can apply a configuration workaround. Administrators can modify Polkit rule configurations to explicitly mandate root authentication for all PackageKit action requests. This configuration change mitigates the vulnerability by preventing unprivileged users from initiating the required D-Bus transactions.
Security operations teams should implement specific log monitoring to detect exploitation attempts. SIEM platforms must monitor system logs for the string PackageKit:ERROR:../src/pk-transaction.c:514:pk_transaction_finished_emit: assertion failed. The presence of this log entry indicates localized attempts to trigger the state machine race condition.
The architectural takeaway for software developers centers on strict state validation. Privilege-granting operations must lock required property states at the time of authorization and enforce rigid state machine transitions. Permitting asynchronous state mutation subsequent to authorization inherently produces critical security flaws.
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
PackageKit PackageKit | >= 1.0.2, <= 1.3.4 | 1.3.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-367 |
| Attack Vector | Local |
| CVSS Score | 8.8 |
| Impact | High (Privilege Escalation) |
| Exploit Status | Proof of Concept |
| KEV Status | Not Listed |
The software checks the state of a resource before using that resource, but the resource's state can change between the check and the use in a way that invalidates the results of the check.