
Repository dedicated to CVE-2026-41651, containing vulnerability-specific information and analysis for this single security issue.
🛡️ AI Security Tool Module
CVE-2026-41651: PackageKit TOCTOU Local Privilege Escalation (Pack2TheRoot)
Official Security Audit & Exploitation Module for AI Security Tool Ecosystem
🌐 Web Demo • 📚 Project Website • 💬 Community Chat
Website Navigation: Home • Updates • Downloads • Modules
This module provides diagnostic tools and deep technical analysis for CVE-2026-41651 (Pack2TheRoot), a critical Time-of-Check to Time-of-Use (TOCTOU) race condition in PackageKit's transaction handler (packagekitd).
The vulnerability allows any local unprivileged user to bypass authorization checks and install arbitrary packages as root with no authentication required.
| Specification | Assigned Value | Notes |
|---|---|---|
| CVE Identifier | CVE-2026-41651 |
PackageKit TOCTOU Local Privilege Escalation |
| Component | PackageKit daemon (packagekitd) |
Core transaction handler |
| Affected Versions | 1.0.2 – 1.3.4 |
Unpatched daemon releases |
| Fixed In | 1.3.5 |
State guard added in transaction handler |
| Impact & Vector | Local Privilege Escalation → root | No authentication or user interaction required |
| Tested Platforms | Ubuntu 24.04, Debian 12 | Standard system configurations |

Three distinct bugs in src/pk-transaction.c chain together to create a TOCTOU window between authorization and execution:
InstallFiles() unconditionally overwrites cached_transaction_flags and cached_full_paths with no state check.pk_transaction_set_state() silently drops backward transitions while flags remain overwritten.pk_transaction_run() reads cached flags at dispatch time from GLib idle, not authorization time.PK_TRANSACTION_FLAG_SIMULATE (bit 2, value 0x4) skips the polkit check entirely.Attacker packagekitd
│ │
│ CreateTransaction() │
│─────────────────────────────────►│ state = NEW
│◄─────────────────────────────────│
│ │
│ InstallFiles(SIMULATE, dummy) │
│─────────────────────────────────►│ SIMULATE → polkit skipped
│◄─────────────────────────────────│ state = READY
│ │ g_idle_add(run_idle_cb) ← queued
│ │
│ InstallFiles(NONE, payload) │ [BUG 1] flags + paths overwritten
│─────────────────────────────────►│ [BUG 2] set_state(WAITING_FOR_AUTH)
│◄─────────────────────────────────│ → silently rejected
│ │ state stays READY
│ │
│ │ [idle fires]
│ │ pk_transaction_run()
│ │ [BUG 3] reads NONE + payload
│ │ → dpkg installs payload as root
│ │ → postinst: chmod +s /bin/bash
│ │
│ execv("/tmp/.suid_bash -p") │
│─────────────────────────────────►│
│ euid=0(root) │
Both InstallFiles calls are sent as fire-and-forget async D-Bus calls before the client's main loop iterates. Polkitd eventually returns NOT_AUTHORIZED for the second call, but by then APT has already dispatched the installation.