AlpacaX

Engineering

Session-scoped sudo: bind OS-level root to a session, not a sudoers file

A sudoers rule only asks who's allowed to run a command. Sudo reaching Alpacon's command API asks a second question: is this command dangerous.

Jungyeon Lee
Jungyeon LeeContent Marketer · August 26, 2026

A sudoers file answers exactly one question: is this identity allowed to run this command pattern as root. It has no way to ask a second one—nothing about a sudoers entry looks at what the command actually does, how risky it is, or why someone's running it right now. "Is this identity in the file" and "is this specific action worth a second look" are two different questions, and a sudoers file only ever answers the first.

Alpacon's answer is to stop attaching sudo to an identity and start binding it to a Work Session—for a human operator or an AI agent alike. Where Alpacon's AI judgment tier is enabled, a sudo call that reaches the command API path gets that second question asked: a rules-and-judgment pass that looks at what the command actually does, independent of whether the identity is authorized to be there at all. Here's the mechanism, and exactly how far it reaches today versus where it doesn't yet.

Why a standing sudoers grant is the wrong shape

A classic sudoers entry is binary and durable: present or absent, until someone edits the file. It doesn't know what task the grant was for, it doesn't expire on its own, and it trusts its own logic to work correctly every time it's invoked.

CVE-2026-35535 (CVSS 7.4, a local, high-complexity attack path, patched in commit 3e474c2 for sudo versions through 1.9.17p2) is a privilege-escalation flaw that lived inside sudo itself: a failure in the setuid/setgid/setgroups privilege-drop calls, made before running sudo's mail-notification component, wasn't treated as fatal. When that failure happened, sudo kept running with elevated privileges it should have dropped.

A session boundary wouldn't have caught that failure—it happened inside sudo's own privilege-drop path, a layer below anything a session judges. What binding sudo to a session changes is what gets asked at each call: a sudoers rule can only ever answer whether this identity is allowed to run this pattern, never whether the specific command is dangerous. Where Alpacon's AI judgment tier is enabled, a sudo call reaching the command API path gets asked that second question too, and the verdict is recorded every time. That's the question a standing sudoers grant structurally can't ask: not just who's allowed, but whether the specific command itself is dangerous.

What a Work Session actually binds to a sudo call

Alpacon's execution-control layer covers OS-level sudo alongside Websh, the command API, and MCP. A Work Session is opened with an identity, a required declared intent, and a set of scopes; where Alpacon's AI judgment tier is enabled, a command that reaches sudo through the command lane is scored by the same three-tier engine as any other command, with the declared intent sitting beside the command line on the approver's card. Without that tier enabled—the default on a self-hosted deployment—the risk pass doesn't run at all, and sudo through the command lane falls back to the same authorization-only check a sudoers file makes. What judgment a sudo call actually gets depends on which channel it arrives through and on that tier being enabled—more on both below.

Concretely: an engineer driving the command API, or an agent, opens a session with intent "restart the app tier on web-03" and a sudo scope on that host. A sudo policy—the separate object that carries the command allow-list—permits systemctl there, so sudo systemctl restart nginx clears without friction.

sudo cat /etc/shadow from the same session is a different story: it isn't on that allow-list, and it matches Alpacon's rules layer directly—40+ patterns covering reverse shells, fork bombs, disk wipes, and credential theft—as credential harvesting. The rules layer computes a deny verdict on the spot: no LLM judgment involved, and no approver in the loop either.

A command that doesn't cleanly match the allow-list or a known-dangerous pattern doesn't default to yes or no—it lands in a grey zone (roughly a 0.3–0.8 risk score) and goes through an LLM judgment layer instead. Toward the low end of that range, a present human's session auto-approves and an agent-mode session holds for approval, since there's no one there to vouch for it; toward the high end, both modes route to a human by default. Either way, that approval happens over console or Slack, never through the channel that requested it, so an agent's CLI or a service token can't approve its own escalation. This is the question a sudoers file has no way to even ask: not "is this identity in the file," but "is this specific, unlisted command worth a second look."

A sudoers entry answers one question and stops there. Sudo reached through the command API path answers that same authorization question, then asks a second one no sudoers file can ask at all: what does this specific command actually do. Whether that second answer changes the outcome is a deployment choice—Alpacon can deny a command the risk pass flags, or hold it for approval before it runs—but the shipped default posture is monitor-and-record: the judgment happens and is logged every time, whether or not today's deployment acts on it.

Where the coverage actually stops

Several paths sit outside the session model, and one sits inside it without its checks ever running. All of this is scoped to hosts Alpacon governs: where the integration isn't installed and active on a host, sudo behaves exactly as it always has—the local rule, the local prompt.

The first: if a system account has no linked identity—a shared or service account—sudo through that account skips policy, MFA, and risk judgment altogether. The session model only governs sudo reached through an identity it knows about; an unlinked account is invisible to it by construction. Linking the account to an identity closes this gap.

The second: a direct SSH login to a host as a local user sits outside Alpacon's session layer entirely. Alpacon can now detect those logins and surface them under Governance → External access, but it can't gate them—stopping that path is a committed design, not something shipped now. So a local login remains a real way to reach a host—and any sudo run from inside it—without ever opening a session.

The third: a service token (for CI/CD or a vendor integration) or a personal API token can also run privileged commands with no Work Session in the picture at all. A service token is governed by a static, admin-approved ACL fixed when it's issued—not by a session's scope, intent, or TTL—so anything it runs never passes through the session model's clock in the first place. Scoping that ACL narrowly is the mitigation available today.

And one sits inside the model rather than around it: a session opened directly with the target account root—available only when a workspace turns on a setting that's off by default—already holds root for the session's entire life. None of the checks a scoped sudo call would pass ever run against it: no sudo policy, no presence check, no risk gate. The session already has, ungoverned, what the sudo scope would have granted under judgment. Leaving that setting off, which is the default, keeps this path closed.

There's a narrower split for the surfaces the session model does reach. Where the AI judgment tier is enabled, a sudo call that reaches the exec lane—the command API path—runs through the three-tier verification engine described above: rules, a baseline layer, and LLM judgment for the grey zone. Sudo reached through an interactive Websh session has no content ceiling at all, tier enabled or not—it's resolved by identity and recency only. Agent-mode sessions are barred from the Websh scope at session creation, so an agent's sudo calls only ever reach the exec lane described above. A human working in an interactive shell doesn't get that same routing—Websh sudo for a human is identity-and-recency only.

The question a sudoers file can't answer

A sudoers file answers "is this identity in the file"—and that's the only question it's built to answer, no matter what the command actually does. Where Alpacon's AI judgment tier is enabled, sudo reached through the command API path answers that question too, then asks a second one sudoers has no way to ask: is this specific, unlisted command dangerous. A sudoers rule doesn't carry a session or a declared intent—it just matches. A command reaching Alpacon through the command API carries both, and on top of them, its own risk gets judged—and recorded—every time it runs, whether or not today's deployment acts on the verdict.

If you're deciding how OS-level privileged access should work for agents and humans running commands on production infrastructure, that's the layer worth evaluating first—not whether the sudoers file is well-maintained, but whether privilege has a session boundary at all.

FAQ

Does a session boundary stop every sudo vulnerability? No. A flaw inside sudo's own privilege-drop code, like CVE-2026-35535, sits below anything a session judges—no session boundary would have caught it. What changes is what gets asked at each call afterward: a sudoers rule can only ever answer who's allowed; Alpacon's sudo path, where the AI judgment tier is enabled, also asks whether the specific command is dangerous.

What happens to sudo judgment when the AI judgment tier is off? Sudo through the command lane falls back to the same authorization-only check a sudoers file makes—no risk pass runs. The AI judgment tier is off by default on a self-hosted deployment, so which judgment a given sudo call gets depends on the channel it arrives through and on that tier being enabled.

Tags:
  • Sudo
  • Privileged access
  • Work Sessions
  • Zero standing privilege
  • Execution control
  • AI-native PAM
Jungyeon Lee
About the authorJungyeon LeeContent Marketer

Jungyeon Lee writes about AI agent security at AlpacaX—mostly incident analyses of agents that went wrong in production, plus the governance side of it, from ISO 42001 readiness to AI vendor risk. She studied economics and web programming at NYU.


Session-scoped sudo: bind OS-level root to a session, not a sudoers file | AlpacaX