dgxcode

Desktop Authentication Service Takeover via Unrestricted Plugin Capability Inheritance

How a logic discrepancy between a command-line plugin validator and an in-process QML runtime allowed untrusted third-party desktop plugins to inherit privileged authentication capabilities and hijack the lock screen.

The target

Modern desktop environments often provide plugin systems that allow developers to customize shell widgets, lock screens, and system trays. In a public open-source desktop shell, developers introduced an explicit security boundary to isolate authentication prompts: sensitive capabilities like ["authentication"] were strictly limited to verified first-party services (such as polkit and lock), managed by a central AuthServiceStore.

Plugins installed by users run with low privileges and are subject to validation by an official CLI tool prior to installation.

The vulnerability

When examining the codebase, a subtle discrepancy was discovered between what the CLI validator enforces versus what the runtime actually consumes:

  1. The Hardening Rule: The CLI validator checks plugin metadata against an explicit list of prohibited capabilities to prevent third-party plugins from requesting authentication privileges directly.
  2. The Inheritance Loophole: The architecture supports a clonedFrom directive in the plugin manifest, originally designed to let fork maintainers base custom plugins on standard templates:
{
  "id": "custom-helper",
  "name": "Custom Helper",
  "omarchy": {
    "clonedFrom": "omarchy.polkit"
  }
}
  1. The Runtime Discrepancy: While the validator only checks top-level declared capabilities, AuthServiceStore.js in the runtime resolves capabilities by checking the plugin's ancestry: if a plugin declares clonedFrom: "omarchy.polkit", the runtime automatically assigns it the full privileged authentication capability set without verifying cryptographic signatures or namespace ownership.

Empirical verification

To confirm the attack chain end to end:

  1. Validation Pre-Flight: A minimal plugin manifest was crafted containing the clonedFrom attribute pointing to the core omarchy.polkit identifier. The official validator CLI was executed:
$ omarchy-plugin-validate ./test-plugin
Validation successful. Plugin manifest is well-formed.
$ echo $?
0
  1. Runtime Execution: The plugin was placed in the local plugin directory and loaded into the desktop shell. Upon execution, the custom plugin successfully registered itself as the active AuthService instance in AuthServiceStore, replacing the default system PAM/Polkit authentication handler.
  2. Exploitation Impact: When an administrative task (such as sudo or package management) triggered a privilege escalation dialog, the user's password input was routed directly to the third-party plugin's callback rather than the verified system polkit agent, allowing plain-text credential capture.

Remediation

The fix requires aligning the validation logic with the runtime capability store:

  • Enforce that privileged capabilities (authentication, session-control) can only be granted to plugins whose IDs match a hardcoded, cryptographically verified first-party allowlist.
  • Strip or neutralize privileged attributes inherited through clonedFrom whenever the plugin origin is external.
  • Unify the validation rules into a single shared parser used by both the CLI tool and the desktop runtime.

The finding was submitted with a runnable demonstration plugin and patch recommendations.