Home / Alt manpages / pkexec(1)

  • pkexec(1)
  • User command
  • linux

Run a Specific Command with pkexec Without Losing the Safety Boundary

You will use pkexec to start one named command as root or another user, check what happened, and understand why a command may fail before it starts. This guide targets pkexec 124 from the Ubuntu package pkexec 124-2ubuntu1.24.04.4. Allow about ten minutes for a careful first test. You need an installed polkit policy and an authentication agent, or a terminal agent that you deliberately start for this session.

Safety boundary

Pkexec starts a privileged process. Inspect the complete program path and every argument before authenticating. The examples below use read-only commands and do not alter system configuration.

1. Confirm the installed command

Run this as your ordinary user. Do not add sudo; the point is to let polkit decide whether authentication is needed.

$ command -v pkexec
/usr/bin/pkexec
$ dpkg-query -W -f='${Package} ${Version}\n' pkexec
pkexec 124-2ubuntu1.24.04.4
$ pkexec --version
pkexec version 124

The local manual documents --version, --help, --disable-internal-agent, --keep-cwd and --user. The final command and its arguments are not options for pkexec once the program has been identified.

Checkpoint

You are using /usr/bin/pkexec, and its version is known.

2. Run a harmless command as root

Use an absolute path for the child. id only reports identity, so it is a useful smoke test. The default target user is root when --user is omitted.

$ pkexec /usr/bin/id
uid=0(root) gid=0(root) groups=0(root)

Your groups and the exact formatting can differ. The useful result is that the child reports uid 0 and pkexec exits successfully. Authentication may appear in a graphical agent. If no agent is available, pkexec 124 attempts its own textual agent.

This command requires authorisation according to the active polkit policy. Never treat a successful prompt as proof that an arbitrary later command is safe: each command and its arguments still need review.

3. Check the exit status separately

pkexec normally returns the child program's status. Capture it immediately after the command if a script needs to distinguish success from failure.

$ pkexec /usr/bin/sh -c 'exit 7'
$ printf 'child status: %s\n' "$?"
child status: 7

The shell in this example is deliberately given a fixed command, not user input. The status 7 comes from the child. According to the manual, pkexec uses status 127 when authorisation cannot be obtained or another error prevents execution, and status 126 when the user dismisses the authentication dialog. Do not use those numbers as a substitute for logging the actual diagnostic.

4. Choose another target user explicitly

Use --user when the command should run as a named account. The account must exist and the active policy must permit the operation.

$ pkexec --user root /usr/bin/id -un
root

Although this repeats the default root target, it makes the intended identity visible in a script or runbook. For a non-root account, replace root with a real local user name and verify the result:

$ pkexec --user BACKUP_USER /usr/bin/id -un
BACKUP_USER

BACKUP_USER is a placeholder, not a literal account. Check it before running the command:

$ getent passwd BACKUP_USER
BACKUP_USER:x:1002:1002:Backup account:/home/BACKUP_USER:/usr/sbin/nologin

Do not create or modify an account merely to make this example work. If getent prints nothing, stop and use an account that your system administrator has already provisioned.

5. Understand the working directory

By default, pkexec runs the child in the target user's home directory. That surprises commands which use relative paths. Use an absolute path for both the program and important files, or add --keep-cwd when retaining the caller's current directory is intentional.

$ pwd
/srv/example
$ pkexec /usr/bin/pwd
/root
$ pkexec --keep-cwd /usr/bin/pwd
/srv/example

--keep-cwd changes where the privileged process starts, not which files its arguments name. Review permissions and paths before authenticating. If a command wrote to the wrong place, stop it if it is still running and restore the affected file from your normal backup. There is no general undo operation for a command started by pkexec.

6. Treat the environment and arguments as security boundaries

pkexec gives the child a minimal, known environment rather than passing through variables such as LD_LIBRARY_PATH. It sets PKEXEC_UID to the uid of the invoking process. A privileged program should therefore not assume that your ordinary shell environment, aliases or search path is present.

The default environment also means ordinary X11 applications usually do not work through pkexec because DISPLAY and XAUTHORITY are removed. An action may explicitly retain them with the org.freedesktop.policykit.exec.allow_gui annotation, but the manual discourages that for anything except legacy programs. Do not work around a GUI failure by copying authentication variables into a privileged command.

pkexec does not validate the arguments passed to the child. This matters when a polkit action lets a user retain authorisation or is implicitly authorised. Keep the program path fixed, quote data arguments, and avoid constructing a privileged command from unchecked text. A rule that permits a script to receive arbitrary arguments can be equivalent to permitting a root shell if that script handles those arguments poorly.

7. Diagnose a failed authentication attempt

Run this from a real terminal when you need to see whether an agent is available:

$ pkexec /usr/bin/true
Error creating textual authentication agent: Error opening current controlling terminal for the process (`/dev/tty'): No such device or address
$ printf 'pkexec status: %s\n' "$?"
pkexec status: 127

The exact message depends on the session. In a graphical desktop, check that a polkit authentication agent is running. In a service, container or non-interactive job, there may be no agent at all. A terminal agent can be registered separately with pkttyagent, but that is a session setup decision, not something to add blindly to an automation script.

--disable-internal-agent prevents pkexec from registering its fallback textual agent. Use it only when another agent is deliberately managed by the calling environment. It does not bypass authentication.

Done means

  • You checked the installed pkexec path and version.
  • You reviewed the full command before authenticating.
  • You verified the target identity and, where relevant, the working directory.
  • You can distinguish the child's exit status from pkexec's authentication failures.
  • You understand that the environment is sanitised and GUI variables are normally absent.
  • You have not relied on unchecked arguments or assumed that a privileged command has an automatic undo.