Back to Blog

Operator-Driven Elevation: Why the Linux Agent Isn't Root

Christopher 6 min read
securityelevationauditlinux

The Linux agent runs as an unprivileged service user. Privileged commands invoked from the dashboard or AI live session require a per-action authorization step that captures the operator's identity, IP, and timestamps in an immutable audit record. This document describes the elevation flow and the audit data model.

Agent privilege model

The Linux agent installs as the etducky user under a hardened systemd unit. It does not have a passwordless sudoers entry, cannot read /etc/shadow, cannot install packages, cannot modify /etc/fstab, and cannot stop or start arbitrary services. The systemd unit's capability bounding set restricts the agent to the capabilities required for eBPF capture and the operator-elevation flow. cgroup limits cap CPU at 50%, memory at 512 MB, and task count at 256.

The narrowed sudoers drop-in at /etc/sudoers.d/etducky-rmm grants NOPASSWD only for read-only diagnostic binaries: smartctl, dmidecode, lshw, lspci, lsusb, journalctl, dmesg, and the agent's own service-restart command (systemctl restart etducky-agent). Other commands that modify host state route through the operator-elevation flow.

Elevation flow

When an AI live session generates a privileged command (for example, sudo hostnamectl set-hostname web-04 in response to an operator request), the agent does not execute the command. It posts an elevation request to the cloud API containing the command summary, full command text, and a nonce. The backend persists the request to a per-organization table with status pending and a 5-minute expiry, then pushes a Server-Sent Event to the operator's dashboard.

The dashboard displays a modal containing the command and a prompt for the host's sudo password. The password is a host-local credential and is not a cloud credential.

The operator types the password and clicks Authenticate. The dashboard POSTs (nonce, password) to the cloud API. The backend validates the nonce age and the match between the operator's Clerk organization and the agent's organization, records the operator's Clerk user id, source IP, and user agent on the request row, and forwards the password to the agent over the SSE channel that delivered the original command. The password is encrypted in transit, is not logged, and is zeroed in agent memory after use.

The agent runs the command via sudo -S bash -c '<cmd>' with the password supplied on stdin, then POSTs the result (exit code, error summary) to the cloud. The audit row status transitions from pending to granted to executed or failed. Status transitions are append-only; the row is immutable after completion.

Audit row contents

ColumnContents
NonceUUID identifying the request. Not reused.
AgentId, OrganizationId, SessionIdTenant scoping. Row-level security restricts visibility to the originating organization.
CommandSummary, CommandTextSummary text shown to the operator at authorization time, and the full command string.
CreatedAt, ExpiresAt, AuthenticatedAt, ExecutedAt, CompletedAtLifecycle timestamps.
AuthenticatedClerkUserIdClerk user id of the operator who authenticated the request.
AuthenticatedFromIp, AuthenticatedUserAgentSource IP and browser user agent at authentication time.
StatusOne of pending, granted, denied, executed, failed, expired. Append-only.
ExitCode, ErrorSummaryOutcome of the command, displayed inline in the dashboard.

Passwords are not stored in the audit row, the cloud database, or persistent agent state. The audit row contains metadata about the authorization event, not the credential used to authorize.

Failure mode descriptions

If the agent's service account is compromised (stolen bearer token, container escape from a co-resident workload, lateral movement from another etducky-running process), the attacker obtains access to: the host's read-only diagnostic surface, the bearer token authenticating to one specific organization, and the eBPF event stream the agent reads. The attacker does not obtain root privileges on the host. Privileged commands require an operator to authenticate at the dashboard with the host's sudo password; the command summary is visible to the operator before authentication.

If an operator's dashboard account is compromised (stolen Clerk session, phished credentials), the attacker can authenticate elevation requests from that account. The audit row records the Clerk user id, source IP, and user agent of the authenticating session. The forensic trail identifies the compromised account.

Current and planned execution mechanisms

The current implementation passes the operator's sudo password over the SSE channel and feeds it to sudo -S on stdin. The password is encrypted in transit, is not logged, and is zeroed in agent memory after use.

Planned changes replace sudo -S for systemd-managed actions (hostnamectl, systemctl, timedatectl, networkctl, journalctl) with polkit rules and D-Bus calls. The dashboard authorization step remains; the response becomes yes/no instead of a credential. A similar change is planned for package management via PackageKit's D-Bus interface.

Windows agent

The Windows agent currently runs as LocalSystem for ETW kernel access. Operator-attributed elevation on Windows is planned. The audit row shape (request, grant, execution, attribution) is intended to be identical across operating systems. On Windows, the on-host execution mechanism will be UAC consent (for interactive approval) or Windows Service Manager APIs (for service-managed actions).

ET Ducky

Documentation and pricing are available on this site. The Linux agent runs as the unprivileged etducky user at install time.

View Pricing