Security Architecture of Authorisation and Authentication UIs on the Linux Desktop

A deep architectural analysis of password prompts and permission dialogs on modern Linux: how Wayland, polkit, PAM, and xdg-desktop-portal isolate credentials and capabilities as of 2026.

20 min read
ibrahimsql
3,830 words

Security Architecture of Authorisation and Authentication UIs on the Linux Desktop#

On a Linux desktop, two dialog boxes presented to an end user can appear almost indistinguishable at first glance: one asks, "This application wants to record your screen; allow access?", while the other requests, "Enter your administrator password to perform a privileged action."

The first interaction is an authorisation decision: it determines whether an existing process is permitted to exercise a restricted capability. The second interaction is an authentication challenge: it verifies whether the human seated in front of the console is genuinely the identity they claim to be.

In desktop security architectures, these two boundaries are frequently conflated or collapsed into the same user experience patterns. Yet the assets protected, the threat models, and the systemic consequences of a failed defense are radically distinct. Under legacy X11, both dialog classes were vulnerable to eavesdropping, synthetic input injection, and UI spoofing for decades.

In the modern Linux architecture, the display server (Wayland compositor), the privilege authority (polkit), the modular authentication stack (PAM), and application sandboxing brokers (xdg-desktop-portal) coordinate to form an isolated, compartmentalised boundary.

This document dissects the end-to-end security architecture of authorization and authentication interfaces on the Linux desktop - from hardware input and kernel device abstractions to D-Bus IPC, compositor surface isolation, and practical auditing workflows.


1. The Core Distinction: Authorisation vs. Authentication#

Disentangling authorisation from authentication is the foundational requirement for building a sound desktop threat model.

+--------------------------------------------------------------------------+ | USER PROMPT | +-------------------------------------+------------------------------------+ | +----------------------------+----------------------------+ | | v v +---------------------------------+ +---------------------------------+ | AUTHORISATION | | AUTHENTICATION | +---------------------------------+ +---------------------------------+ | Question: "May this process | | Question: "Are you who you | | perform action X?" | | claim to be?" | | Asset at Risk: A permission | | Asset at Risk: Credentials / | | Target: Capability delegation | | Session tickets | | Output: Ephemeral Allow / Deny | | Target: Identity verification | | Blast Radius: Scope expansion | | Output: Cryptographic assertion | | for one process | | Blast Radius: Account takeover, | +---------------------------------+ | credential theft | +---------------------------------+

Comparative Analysis Matrix#

CriterionAuthorisationAuthentication
Core QuestionMay this process (PID / App ID) access the target resource?Is the human operator authenticated as this system account?
Data ProcessedPermission bit (Allow/Deny), capability token, expiryPassword plaintext, FIDO2 assertion, PAM session token
Asset at RiskRuntime capability (screen capture, camera, raw input)Master credentials, root privilege, session keyring secrets
Cost of Spoofed UILow-Moderate: Tricking the user into clicking "Allow" on a fake prompt does not grant the underlying kernel/compositor capabilityCritical: Tricking the user into typing a password hands over raw credentials; enables arbitrary privilege escalation
Invocation FlowPortal D-Bus calls (xdg-desktop-portal), polkit rule checksPAM conversation (pam_authenticate), polkitd agent dispatch
User InteractionSingle-click confirmation, resource scope pickerPassword entry, biometric scan, hardware FIDO2 tap

This structural asymmetry is paramount: If an attacker crafts a pixel-perfect fake authorisation dialog and tricks the user into clicking "Yes", the attacker gains nothing unless the underlying operating system and compositor actually provision the capability.

Conversely, if an attacker paints a fake authentication dialog, the user types their plaintext root or administrative password directly into the attacker's process memory. The attacker can then programmatically invoke sudo or polkit interfaces at will.


2. End-to-End System Security Architecture#

Authorising an action or authenticating an identity on a modern Linux workstation traverses a structured stack spanning from the physical hardware to the desktop shell.

+-----------------------------------------------------------------------------+ | UNTRUSTED CLIENT | | (Sandboxed Flatpak / Unprivileged Host App / Malicious Process) | +--------------------------------------+--------------------------------------+ | 1. D-Bus Request | (org.freedesktop.portal.* or | org.freedesktop.PolicyKit1) v +-----------------------------------------------------------------------------+ | AUTHORITY & BROKER LAYER | | | | +---------------------------+ +----------------------------------+ | | | xdg-desktop-portal | | polkitd | | | | (User Session Bus) | | (System D-Bus / Root) | | | +-------------+-------------+ +-----------------+----------------+ | +----------------|----------------------------------------|-------------------+ | 2. UI Request | 2. Agent Dispatch v v +-----------------------------------------------------------------------------+ | TRUSTED SHELL & COMPOSITOR LAYER | | (GNOME Shell / KDE Plasma / wlroots) | | | | +---------------------------+ +----------------------------------+ | | | Portal Frontend Backend | | polkit AuthenticationAgent | | | | (gnome/kde/wlr portal) | | (Embedded in Shell or Agent) | | | +-------------+-------------+ +-----------------+----------------+ | | | | | | +-------------------+--------------------+ | | | | | v | | +--------------------------------------+ | | | Wayland Compositor | | | | (Surface Isolation, Exclusive Grab)| | | +------------------+-------------------+ | +------------------------------------|----------------------------------------+ | 3. Auth IPC v +-----------------------------------------------------------------------------+ | KERNEL & SYSTEM SECURITY BOUNDARY | | | | +-----------------------+ +----------------------+ +------------------+ | | | polkit- | | PAM Stack | | Linux Kernel | | | | agent-helper-1 |->| (pam_unix, pam_fido2,|->| (evdev, DRM, | | | | (setuid root) | | pam_systemd_home) | | cgroups, bwrap) | | | +-----------------------+ +----------------------+ +------------------+ | +-----------------------------------------------------------------------------+

Architectural Breakdown by Layer#

  1. Client Isolation Boundary: If the client runs inside an unprivileged Bubblewrap sandbox (Flatpak/Snap), it lacks direct access to /dev/input/event*, DRM device master nodes, or system D-Bus endpoints. It communicates strictly via filtered D-Bus calls forwarded through the session bus proxy.

  2. Authority & Decision Engine:

    • polkitd: Evaluates system-level authorisation rules written in JavaScript under /usr/share/polkit-1/rules.d/ and /etc/polkit-1/rules.d/.
    • xdg-desktop-portal: Manages per-application runtime permissions via its internal PermissionStore and delegates user prompting to desktop-specific backends.
  3. Trusted Shell & Compositor Boundary: The authentication prompt is never drawn by the requesting application. It is rendered directly by the compositor's own scene graph (e.g., Mutter or KWin). The compositor assigns exclusive keyboard focus to this surface, preventing background clients from observing or intercepting keystrokes.

  4. Execution & Privilege Verification: The password entered into the shell agent is never transmitted over D-Bus in cleartext. The agent forks a setuid binary (polkit-agent-helper-1) that runs the PAM stack locally. Only the final boolean verification status is transmitted back to polkitd.


3. Threat Model and Classical Attack Primitives#

Desktop interface attacks fall into four distinct categories. Wayland and modern Linux IPC resolve several of these structurally, while others require careful human-interface design.

+---------------------+-------------------------+-----------------------------+ | Attack Primitive | Legacy X11 Posture | Modern Wayland & Portal | +---------------------+-------------------------+-----------------------------+ | 1. Keystroke | Completely vulnerable. | Solved at protocol level. | | Snooping | Any client can tap the | Keystrokes are delivered | | | global input stream. | exclusively to focused surface.| +---------------------+-------------------------+-----------------------------+ | 2. Synthetic Input | XTest allows arbitrary | Synthetic input disallowed. | | Injection | event forgery into any | Only authorized libei/EIS | | | focused window. | channels can inject events. | +---------------------+-------------------------+-----------------------------+ | 3. Confused Deputy | High risk via unverified| Mitigated via SO_PEERCRED, | | | IPC messages and paths. | cgroup inspection, portals. | +---------------------+-------------------------+-----------------------------+ | 4. UI Spoofing / | Trivial: full-screen | Addressed via compositor- | | Phishing | fake dialogs indistin- | owned exclusive layers and | | | guishable from root UI. | trusted system indicators. | +---------------------+-------------------------+-----------------------------+

1. Keystroke Snooping#

  • Mechanism: Under X11, any client could call XSelectInput on root windows or invoke the XRecord extension to intercept every keypress across all running processes - including passwords typed into terminal sudo or graphical prompts.
  • Wayland Defense: Wayland does not expose a global event listener. The compositor routes wl_keyboard.key events strictly to the client that owns the currently active wl_surface. When an authentication dialog appears, the compositor transfers focus to its internal surface, cutting off all other clients.

2. Synthetic Input Injection#

  • Mechanism: X11 provided the XTest extension, allowing any program to synthesise mouse clicks and keypresses. An attacker could monitor window creation, wait for a prompt like gksu, and inject keystrokes or simulate a click on "Authorize".
  • Wayland Defense: The core Wayland protocol contains no concept of synthetic client input. Applications requiring emulation (remote desktop tools, accessibility software) must interface with xdg-desktop-portal's RemoteDesktop portal, which negotiates an isolated libei channel requiring explicit user approval.

3. Confused Deputy Attacks#

  • Mechanism: A low-privilege process asks a high-privilege daemon (e.g., systemd or PackageKit) to perform an action, exploiting the daemon's implicit trust in the caller.
  • Modern Defense: D-Bus enforces kernel-level identity verification via SO_PEERCRED. The D-Bus daemon extracts the caller's actual PID, UID, and cgroup directly from the kernel socket. When polkitd checks authorization, it interrogates this kernel-verified identity rather than untrusted client claims.

4. UI Spoofing & Phishing#

  • Mechanism: An unprivileged application paints a window designed to mimic the system authentication dialog, tricking the user into providing credentials.
  • Compositor Defense:
    • Exclusive Top-Level Layer: The compositor places system prompts on a protected top layer (e.g., using ext-session-lock-v1 or compositor-private layers) that cannot be occluded or mimicked by standard client surfaces.
    • Background Dimming and Grabs: The compositor dims all background surfaces and prevents any interaction outside the active modal dialog.
    • Hardware and Status Indicators: High-security desktop environments maintain persistent, un-spoofable status indicators (e.g., system trays, panel locks) that an ordinary application window cannot alter.

4. polkit Authorisation & Authentication Flow#

The following sequence diagram outlines the exact D-Bus IPC protocol interactions during a privileged action request:

Client (App) polkitd AuthAgent (Shell) Helper (PAM) Target Service | | | | | | 1. Request Op | | | | +---------------------------------------------------------------------------->| | | | | | | | 2. CheckAuthorization(subject, action) | | |<---------------------------------------------------------+ | | | | | | | 3. Evaluate Rules (/etc/polkit-1/rules.d) | | | Result: AUTH_ADMIN required | | | | | | | | 4. BeginAuthentication() | | | |+------------------>| | | | | | 5. fork/exec | | | | |+----------------->| | | | | | | | | | 6. Render Prompt | | | | | (Wayland Grab) | | | | | | | | | | 7. Password Input | | | | +------------------>| | | | | | 8. PAM Verify | | | | | (/etc/pam.d) | | | | 9. Exit 0 (OK) | | | | |<------------------+ | | | 10. AuthenticationComplete() | | | |<-------------------+ | | | | | | 11. Auth Result: {is_authorized: true} | | +--------------------------------------------------------->| | | | | 12. Op Result | | |<----------------------------------------------------------------------------+

Protocol Mechanics#

  1. Service Inquiry: When a client invokes a method on a privileged D-Bus service (e.g., org.freedesktop.systemd1), the service calls org.freedesktop.PolicyKit1.Authority.CheckAuthorization.
  2. Rule Evaluation: polkitd executes JavaScript rules in lexical order. If the rule returns polkit.Result.AUTH_ADMIN, interactive authentication is triggered.
  3. Agent Notification: polkitd calls BeginAuthentication on the user session's registered org.freedesktop.PolicyKit1.AuthenticationAgent. In GNOME, this agent is built into gnome-shell. In KDE Plasma, it is polkit-kde-authentication-agent-1.
  4. PAM Separation: The agent spawns /usr/lib/polkit-1/polkit-agent-helper-1 (setuid root). The helper handles the PAM conversation directly. The plaintext password remains strictly within the helper's private memory space and is never exposed over D-Bus.

Deep Source Code Analysis: polkit-agent-helper-1 and PAM Conversation#

The most critical link in the Polkit privilege boundary is polkit-agent-helper-1. The graphical desktop shell (such as GNOME Shell or KWin) executes with standard user privileges (UID 1000) and cannot access the shadow password database (/etc/shadow). Running the entire compositor shell as root would introduce catastrophic security exposure.

To resolve this, Polkit enforces privilege separation via the polkit-agent-helper-1 C binary. The architectural implementation of this interaction is structured as follows:

/* Simplified architectural flow from polkit-agent-helper-1.c */ #include <security/pam_appl.h> #include <string.h> #include <unistd.h> #include <stdio.h> static int conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data) { struct pam_response *aresp; aresp = calloc (n, sizeof (struct pam_response)); if (aresp == NULL) return PAM_BUF_ERR; for (int i = 0; i < n; i++) { if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF || msg[i]->msg_style == PAM_PROMPT_ECHO_ON) { /* Password is read securely from the unprivileged agent over a private pipe connected to standard input (stdin) */ char password_buf[512]; if (fgets (password_buf, sizeof (password_buf), stdin) != NULL) { /* Strip trailing newline delimiter */ password_buf[strcspn(password_buf, "\n")] = 0; aresp[i].resp = strdup (password_buf); aresp[i].resp_retcode = 0; /* Security: Wipe password buffer using explicit_bzero to guarantee memory erasure against compiler optimization */ explicit_bzero (password_buf, sizeof (password_buf)); } } } *resp = aresp; return PAM_SUCCESS; } int main (int argc, char *argv[]) { pam_handle_t *pamh = NULL; struct pam_conv pam_conversation = { conversation_function, NULL }; const char *user_to_auth = argv[1]; int rc; /* 1. Initialize PAM conversation handle for the polkit-1 service */ rc = pam_start ("polkit-1", user_to_auth, &pam_conversation, &pamh); if (rc != PAM_SUCCESS) return 1; /* 2. Execute credential verification */ rc = pam_authenticate (pamh, 0); if (rc == PAM_SUCCESS) { /* 3. Validate account status (expiry, restrictions) */ rc = pam_acct_mgmt (pamh, 0); } /* 4. Terminate PAM transaction and return strictly boolean exit code */ pam_end (pamh, rc); /* Protocol outcome: Exit code 0 indicates success, 1 failure. Password strings are never logged or propagated over D-Bus IPC. */ return (rc == PAM_SUCCESS) ? 0 : 1; }

Key Implementation Takeaways:#

  1. Immunity to Dead Store Elimination (explicit_bzero): Standard memset() calls can be optimized away by modern compilers (-O2 / -O3) if the buffer is not read before exiting the function scope. Polkit uses explicit_bzero() to guarantee that password plaintext is wiped from volatile memory immediately.
  2. Minimal IPC Attack Surface: The interface between the unprivileged agent and the setuid helper is limited strictly to a unidirectional byte pipe (stdin) and process exit status. The helper avoids linking heavy GUI or XML libraries, minimizing the risk of memory corruption vulnerabilities inside the setuid boundary.

Deep Source Code Analysis: polkitbackendjsauthority and SO_PEERCRED#

The decision engine inside polkitd (polkitbackendjsauthority.c) does not trust client-declared metadata. Caller identity is validated directly using Linux kernel socket credentials (SO_PEERCRED):

/* polkitbackendjsauthority.c - Kernel-verified caller extraction */ static PolkitSubject * get_subject_from_dbus_invocation (GDBusMethodInvocation *invocation) { GDBusConnection *connection; GCredentials *credentials; pid_t pid; uid_t uid; connection = g_dbus_method_invocation_get_connection (invocation); /* Interrogate kernel-level Unix domain socket credentials */ credentials = g_dbus_connection_get_peer_credentials (connection); if (credentials == NULL) return NULL; /* Extract kernel-validated PID and UID */ pid = g_credentials_get_unix_pid (credentials, NULL); uid = g_credentials_get_unix_user (credentials, NULL); /* Instantiate immutable Subject entity for JavaScript engine evaluation */ return polkit_unix_process_new_for_owner (pid, 0, uid); }

By extracting credentials directly from the kernel struct ucred via SO_PEERCRED, Polkit renders spoofed D-Bus headers ineffective. Confused deputy attacks cannot disguise an untrusted caller under a privileged process identity.


5. Sandboxed Capability Management via xdg-desktop-portal#

For modern application packaging formats (Flatpak, Snap), requesting root access is an anti-pattern. Instead, portals manage runtime capabilities using dynamic capability delegation and user consent:

+-----------------------+ | Sandboxed Application | | (com.example.app) | +-----------+-----------+ | D-Bus Session Call (org.freedesktop.portal.ScreenCast) v +-----------------------+ | xdg-desktop-portal | <--- Inspects /proc/[PID]/root and cgroups | (Portal Broker) | to verify application identity +-----------+-----------+ | Internal D-Bus Call (org.freedesktop.impl.portal.*) v +-----------------------+ | xdg-desktop-portal- | | gnome / kde / wlr | <--- Trusted desktop backend renders modal: +-----------+-----------+ "com.example.app wants to share your display" | | User approves and selects a specific output or window v +-----------------------+ | Wayland Compositor | | & PipeWire Daemon | <--- Compositor creates DMA-BUF stream via PipeWire, +-----------+-----------+ passes file descriptor (FD) back to portal | v +-----------------------+ | Sandboxed Application | <--- Receives scoped PipeWire FD; | (Consumes Stream) | has zero access to underlying display surfaces +-----------------------+

The Security Context Protocol (wp_security_context_manager_v1)#

The standardisation of wp_security_context_manager_v1 in the Wayland ecosystem closes the residual gap between sandbox runtimes and the display server:

  1. Prior to starting an untrusted client, the sandbox engine (Flatpak/Bubblewrap) calls create_listener on the compositor's wp_security_context_manager_v1 global.
  2. The sandbox engine binds metadata (app_id, sandbox_engine) to the listening socket.
  3. The sandboxed client connects via this scoped socket. The compositor automatically tags all resulting connections as restricted.
  4. Restricted connections are prohibited from binding privileged globals (ext-session-lock-v1, wlr-screencopy, layer-shell), preventing sandbox escape attempts through the display protocol.

Protocol XML Specification and Compositor C Integration:#

The wp_security_context_manager_v1 interface is formally specified in wayland-protocols:

<interface name="wp_security_context_manager_v1" version="1"> <description summary="client listener manager for sandbox engines"> This global interface allows privileged sandbox runtimes (e.g. Flatpak, Bubblewrap) to register an isolated listening socket with the compositor, attaching immutable security metadata to incoming client connections. </description> <request name="destroy" type="destructor"/> <request name="create_listener"> <arg name="id" type="new_id" interface="wp_security_context_v1"/> <arg name="listen_fd" type="fd" summary="listening socket FD"/> <arg name="close_fd" type="fd" summary="teardown notification FD"/> </request> </interface> <interface name="wp_security_context_v1" version="1"> <request name="set_sandbox_engine"> <arg name="name" type="string"/> </request> <request name="set_app_id"> <arg name="app_id" type="string"/> </request> <request name="commit"/> </interface>

Within the compositor (such as wlroots or Mutter), the listening socket is integrated into the display server event loop. When a new sandboxed connection is accepted:

/* Compositor connection acceptance logic */ static int security_context_handle_connection (int fd, uint32_t mask, void *data) { struct security_context_listener *listener = data; int client_fd = accept4 (fd, NULL, NULL, SOCK_CLOEXEC); /* Instantiate client within the compositor display context */ struct wl_client *client = wl_client_create (compositor->display, client_fd); /* Attach verified security context to client handle */ client->security_context = listener->context; // app_id, sandbox_engine return 0; } /* Dynamic registry filtering on wl_registry.bind */ static void registry_bind (struct wl_client *client, struct wl_resource *resource, uint32_t name, const char *interface, uint32_t version, uint32_t id) { /* If client is subject to a sandboxed security context */ if (client->security_context != NULL) { if (strcmp (interface, "ext_session_lock_manager_v1") == 0 || strcmp (interface, "zwlr_screencopy_manager_v1") == 0 || strcmp (interface, "zwlr_layer_shell_v1") == 0) { /* Deny request and emit fatal protocol error to terminate client */ wl_resource_post_error (resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "Privileged interface '%s' denied to sandboxed client", interface); return; } } /* Standard binding flow for unconfined clients */ ... }

This kernel- and protocol-level integration prevents untrusted processes within containers or Flatpak sandboxes from interacting with lock screens, frame grabbers, or global shortcut registries.


6. Practical Security Auditing & Verification Lab#

The following command sequences enable practitioners to audit the authentication and authorization posture of a running Linux workstation.

1. Inspecting Session Isolation#

# Verify the active session type and remote status loginctl show-session "$XDG_SESSION_ID" -p Type -p Desktop -p Remote -p LockedHint
  • Expected Output: Type=wayland, Remote=no.
  • Security Significance: If Type=x11, all surface isolation guarantees are void; any running process can sniff keystrokes and inject synthetic events across the entire session.

2. Auditing polkit Agents#

# Locate active polkit authentication agents on the session bus busctl --user list | grep -i polkit ps -eo pid,user,args | grep -iE 'polkit|authentication-agent'
  • Analysis: On GNOME, the agent runs internally within gnome-shell. On KDE Plasma, verify that /usr/lib/polkit-kde-authentication-agent-1 runs under your user UID. An unrecognised binary registered as an authentication agent indicates potential credential harvesting.

3. Enumerating Privileged Actions & Policies#

# Count total registered actions on the workstation pkaction | wc -l # Inspect the authorization policy of a critical action pkaction --action-id org.freedesktop.systemd1.manage-units --verbose
  • Interpretation: Look for implicit active: yes on sensitive actions. High-risk administrative actions should require auth_admin or auth_admin_keep.

4. Auditing Portal Permissions#

# Inspect registered portal backends busctl --user introspect org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop # List active permission store entries for Flatpak applications flatpak permissions
  • Remediation: Remove stale or over-privileged application capabilities using flatpak permission-reset <app-id>.

5. Checking Raw Input Device Permissions#

# Audit accessibility of the uinput kernel interface ls -l /dev/uinput
  • Expected Permissions: crw-rw---- 1 root input /dev/uinput
  • Vulnerability Indicator: If /dev/uinput is world-writable (0666) or if unprivileged desktop users belong to the input group, untrusted software can instantiate a virtual keyboard device and bypass Wayland input isolation entirely.

7. Common Anti-Patterns and Architectural Failures#

  1. In-App Password Collection: Applications that render their own input fields requesting the user's root or sudo password bypass system trust boundaries. Third-party application pixels must never be trusted with master credentials.

  2. Unsanitized Caller-Supplied Justifications: Allowing unprivileged callers to inject arbitrary reason strings into polkit dialogs creates UI red-dressing vulnerabilities. Shell backends must visually demarcate caller-provided text from trusted system-generated prompts.

  3. Indefinite Authorization Caching: Configuring auth_admin_keep without strict timeout policies allows secondary processes to execute privileged actions without user re-authentication.

  4. Mixed Xwayland Desktop Environments: Running sensitive authentication dialogs inside an unisolated Xwayland context exposes those dialogs to keystroke sniffing by legacy X11 applications running in the same session.


8. Summary: The 2026 Security Posture#

As of 2026, the Linux desktop has transitioned from the ambient-authority model of X11 to an explicit, capability-based security model:

  • Authorisation is mediated by xdg-desktop-portal and libei, enforcing granular user consent and capability scoping without distributing credentials.
  • Authentication is compartmentalised within compositor-rendered shell agents, backed by setuid PAM helpers and hardware tokens (FIDO2, TPM2).
  • Isolation is enforced at the kernel and display-server boundaries via Wayland surface scoping and wp_security_context_manager_v1.

How the password actually gets verified: PAM stack and polkit agents#

When a polkit prompt asks for a password, the "agent talks to polkit" mechanism hides the second half: the agent runs a PAM conversation. polkit delegates the credential check to PAM via pam_start/pam_authenticate using the same stack as local login. A typical desktop stack orders the modules so the first acceptable verifier wins:

  1. pam_fprintd — if the machine has a fingerprint reader, the prompt appears before any password field is filled; a fingerprint match is enough.
  2. pam_unix — classic /etc/shadow password verification.
  3. pam_unix is preceded by pam_faillock/pam_tally2 — this is what turns five wrong tries into a temporary lockout, and it is more than a courtesy feature: it is the anti-bruteforce slab behind the visible dialog.
  4. pam_kwallet/pam_gnome_keyring side stacks open the keyring on successful password auth, so the password both authorises the action and unlocks the user's stored credentials. This coupling is deliberate but often forgotten in threat modeling.

The security property that matters: the password never travels in the clear through polkit or D-Bus. It moves from the agent to the system PAM service over the polkit authority's own privileged channel, and PAM holds it only for the verification window. That is why hijacking the visible prompt is a credential-harvesting attack, not just a UI problem: if the dialog is fake, the typed password goes to the attacker directly.

A test to confirm the prompt is real: reboot, verify the normal keyboard layout and terminal behaviour of the real prompt, and prefer agents that call into a system service. Designs that show a password popup with no PAM check behind it (a client-side "self-check") are worth flagging as an anti-pattern; same for agents that accept any input and then attack polkit with a dump string.

---
Share this post:

What do you think?

React to show your appreciation

Related Posts