---
title: "Session protection"
description: "Learn how Alpacon work sessions limit people and AI agents on your servers. See each command and sudo check, what fails open, and what stays outside a session."
---

> Full documentation index: https://docs.alpacax.com/llms.txt

# Session protection

This page describes what protects your servers while a person or an AI agent works on them through Alpacon, and where that protection ends. It is written for the security reviewer who has to answer two questions: what stops a misbehaving agent or insider, and what fails open.

It describes Alpacon Cloud. Where a self-hosted deployment without Alpacon AI behaves differently, the section says so.

## What a work session guarantees

Interactive access to a server goes through a [work session](/use/work-sessions/). Nobody holds standing access: a person signed in to the console or the CLI can't open a terminal, transfer a file or run a command without an approved, active session that covers it.

A session is a limit the request declares and an approver accepts:

- **Which features**: the web terminal, file transfer, commands, port forwarding, the code editor and sudo, each declared separately.
- **Which servers**: only the servers the session names.
- **For whom**: only the person the session is for can use it.
- **Why**: a written purpose, shown to the approver and kept with the record.
- **Until when**: the session ends at a fixed time, and everything it opened closes.

Every operation is checked against the session when it happens, not only when the session is approved. An operation outside the session is refused, whatever the requester's role.

## Scope and intent

When a session is requested, Alpacon checks what it declares:

- **Features**: an AI agent can't declare the web terminal. An agent session is refused it when it is created, and again if anything tries to open one later.
- **Servers**: the session lists the servers it may reach. A command or connection to any other server is refused.
- **Account**: the session can name the server account to work as, under **Connect as**. An agent session runs only as the account approved for it; any other account is refused. No session can run as an account linked to another person, and no rule or setting lifts that stop.
- **Purpose**: a session must state what it is for, in up to 2,048 characters. The purpose travels with the session: commands are judged against it, and work that drifts from it can be held (see [Per-command checks](#per-command-checks)).

While the session runs, each operation must pass these checks in turn: the session hasn't ended, it is active, it includes the feature, the server belongs to it, and the caller is the person it is for. A Superuser working in the web console can act on another member's session; nobody else can.

## Approval

A new session waits for approval unless a rule admits it:

- **By default**, a session a Superuser requests is approved at once. Every other session waits for one approver, and that includes every AI-agent session, whoever requested it.
- **Approvers** are the people your access rules name. With no rule naming anyone, every active Superuser can approve.
- **Rules** under **Access rules**, on the **Opening a session** tab, can allow a request, ask an approver or block it. An Allow rule for AI agents admits an agent session only when the session states a purpose.
- **Where approval comes from**: an approval is accepted only from the web console or another channel registered for approving. The CLI, MCP client or token that made the request can't approve it.
- **Self-approval**: a requester may approve their own request unless the rule forbids it, and the record marks it as self-approved. When Alpacon can't tell the agent's client from the console, the person who requested an agent session can't approve it.
- **Step-up**: where an approval grants new authority, or your workspace requires MFA for approving, the approver confirms with a fresh MFA check. Signing in with MFA earlier doesn't count.
- **Unanswered requests**: an undecided request is canceled when its requested end passes or the pending limit is reached (24 hours by default), whichever comes first.
- **Changes**: an extension goes through the same rules as a new session. Changing an agent session's purpose, or adding a server to it, needs approval again.

The approval check compares the request with your rules; it does not inspect what the session will do. See [What Alpacon checks, and what it doesn't](/learn/security/what-alpacon-checks/).

## Per-command checks

Each command sent in a work session, through the command API or `alpacon exec`, is judged by Alpacon AI before it reaches the server. The AI rates its risk, approves or rejects it, and compares it with the session's purpose. What happens next, for a command in a work session (a service token's command outside a session is settled differently; see [Access outside a work session](#access-outside-a-work-session)):

| The AI's judgment | A person's command | An AI agent's command |
|---|---|---|
| Approved | Runs | Runs, unless one of the holds below applies |
| Approved, but the AI is not confident | Runs | Held for an approver |
| Off the session's purpose | Held for an approver | Held for an approver |
| Rejected | Held for an approver, who sees why the AI rejected it | Held for an approver, who sees why the AI rejected it |

- **Servers that always need a person**: an agent's command to a server in the `agent-approval-required` server group is always held, whatever the AI says.
- **Held commands** wait in [Approvals](/use/approvals/) and notify the approvers. If the approver approves, the command runs; if they reject it, or nobody decides within 24 hours, it doesn't. If nobody other than the requester could approve it, the command is refused at once.
- **Your rules**: rules on the **Running a command** tab, matched on requester, server group and the AI's rating, can hold, allow or block a command in place of these defaults. No rule lets through a command the AI rejected. A command a rule blocks is refused.
- **Scripts**: a file run as a command must pass the AI's review. A script an approver already cleared runs again without a new hold, as long as it hasn't changed.
- **Commands typed in a terminal**: commands typed in a Websh terminal are not judged one at a time; their `sudo` is (see [sudo and run-as](#sudo-and-run-as)). The whole session gets an AI analysis after it ends.
- **Advisory workspaces**: a workspace in [Advisory execution control](/use/workspace/settings/#execution-control) records every judgment but holds and refuses nothing because of it. Commands run at once, and new sessions are admitted without approval.

You see the result on the command: its status, the AI's rating and, for a held or refused command, the reason. See [Commands](/use/audit/events/commands/).

## sudo and run-as

`sudo` needs the session to declare the sudo feature, for every requester, Superusers included. Then each use of `sudo` is judged on its own, by the risk the AI rates for the elevated command. This table is that per-use check; a command an approver already approved is the [exception below](#approved-commands):

| Rating | A person | An AI agent |
|---|---|---|
| **Info**, **Low** | Allowed, after MFA | Allowed |
| **Medium** | Allowed, after MFA | Held for an approver |
| **High** | Held for an approver | Held for an approver |
| **Critical**, or not rated | Refused | Refused |

- **MFA**: a person proves they are present with a recent MFA check. An agent can't, so for an agent the session's approval stands in for it. A command that runs without a terminal can't ask for MFA; it is refused with `SUDO_PRESENCE_REQUIRED`, and you verify and run it again.
- **Holds**: a held `sudo` creates an approval request. Once it is approved, run the command again.
- <a id="approved-commands"></a>**Approved commands**: when a person approves a held command, that approval also covers each `sudo` written in the command's line, at any rating, Critical included. It doesn't override the session's sudo feature, the account's authority, or a workspace rule that blocks the `sudo`. If you approved your own command, you still confirm with MFA. A `sudo` the approver never saw in the line gets the per-use check above.
- **Tightening only**: your rules on the **Using sudo** tab, and a session's own sudo settings, can turn an allow into a hold. A `sudo` the AI judges off the session's purpose is held. No rule can allow a Critical `sudo`; only a person's approval of the command that contains it can.
- **Session sudo policies**: a session can carry its own sudo policies, bound to its servers and its time window. An agent session that carries them always needs a person to approve it.
- **Run-as**: `sudo -u`, `su` or `runuser` into an account linked to another person is refused, for administrators too, and is never offered for approval. A switch whose target account can't be read is refused the same way. `root`, and accounts not linked to anyone, follow the rules above.

The codes on a refused `sudo` and what to do about each are in [PAM issues](/use/work-sessions/terminal/troubleshoot-sudo/).

## Time bounds

- **Workspace maximum**: a session can't be longer than the workspace's **Maximum session duration**, 4 hours by default. A Superuser sets it in [workspace settings](/use/workspace/settings/), between 5 minutes and 7 days. A request for longer is refused, not shortened.
- **Scheduled start**: a session can start at a future time. It does nothing until then.
- **Expiry warning**: the requester and the person the session is for get a notice to extend it a few minutes before it ends.
- **Extension**: a session that has started can be extended, with a reason, through the same approval rules. The new end can't be more than the workspace maximum from the moment you ask.
- **At the end time**: every new operation is refused at once with `work_session_expired`.

## Ending a session

| How it ends | Who | From |
|---|---|---|
| Complete | The person the session is for, or a Superuser, with **Complete session** | An active session |
| Revoke | A Superuser, with **Revoke session** | An approved or active session |
| Expire | Alpacon, at the end time | An approved or active session |
| User removed from the workspace | Alpacon, when the user is deleted | Every approved or active session for that user |

Each of these four closes everything the session opened:

- **Terminals**: open Websh terminals close, and the browser shows why.
- **Tunnels**: port forwards and code editor connections close.
- **File transfer**: open WebFTP sessions close.
- **Queued commands**: commands not yet delivered to a server are cancelled, including commands held for approval.
- **sudo policies**: the session's own sudo policies stop applying. They stay in the record.

Pending change requests on the session are cancelled too. Completing or revoking closes everything at once; an expired session's open connections close within a few minutes, and nothing new is allowed in the meantime.

A pending session that is cancelled or rejected never opened anything, so there is nothing to close.

Deactivating a user, rather than removing them, closes their open terminals and file transfers at once, and they can't sign in again to use their sessions.

## When Alpacon AI is unavailable

If Alpacon AI can't answer, Alpacon doesn't wait indefinitely. What happens depends on what was asked:

- **Commands in a session** run without the AI's approval and are marked **Skipped** in command history. Rules that don't depend on the AI still apply: a command your rules hold for its requester or server is still held, and so is an agent command to a server in `agent-approval-required`, or a command the AI already found off-purpose in this session.
- **Files run as commands** are refused, because a script can't run without the AI's review.
- **Commands sent with a service token** are refused, because their pre-approval can't be checked.
- **sudo in a command** is refused, since the command has no rating, unless the session carries a sudo policy that skips MFA.
- **sudo in a Websh terminal** falls back to the normal sudo checks: a matching sudo policy, an approver where your rules ask for one, and MFA.
- **Session approval** doesn't use the AI, so it works as usual.

On a self-hosted deployment without Alpacon AI, commands run without a judgment and are marked **Skipped**, files can't be run as commands, `sudo` in a session follows your sudo policies and MFA, and `sudo` with a service token is refused.

## Access outside a work session

Commands run inside a work session, or through a service token under its access-control rules. The one exception is a personal API token that already runs commands, described below. Three kinds of credential reach the API without a work session, and a security review should list them:

- **Service tokens**: automation tokens issued to an [application](/use/iam/applications/). A service token works within its scopes and its server, command and file access-control rules, its allowed IP ranges and hours, and its rate limit. Outside Advisory, an AI rejection of a service token's command is recorded and the command still runs, unless the AI rates it Critical; your rules can tighten that. On Alpacon Cloud, service-token sudo is allowed below Critical, including unassessed commands, and refused at Critical unless the workspace is Advisory. In Advisory, it is not refused for risk at any level, and the decision is recorded. Outside Advisory, a workspace `token_exec` rule can tighten the risk threshold. The workspace sudo setting must be on; otherwise sudo is refused with `workspace_sudo_with_mfa_disabled`. On a default self-hosted install, every service-token sudo is refused. Sudo policies do not apply to service tokens; they do apply to personal API tokens. See [Service tokens](/use/iam/applications/service-tokens/).
- **Registration tokens**: used once to register a server. They can only register servers.
- **Personal API tokens**: New personal API tokens cannot hold command-execution or file-transfer scopes. Existing tokens with those scopes keep working without a work session. Use a [service token](/use/iam/applications/service-tokens/) for automation and CI.

None of these can open a Websh terminal, the code editor or a WebFTP session; those need a signed-in person. For automation, use service tokens: their limits are set by an administrator and every use is recorded under the application.

**External access is detected, not blocked.** Logins that reach a server without Alpacon (SSH, the local or cloud console, `su`) are outside any work session. With **Direct-login detection** turned on, which is off until someone turns it on, Alpacon records each one and asks a reviewer about the ones you haven't marked as expected. It never stops the login. To keep `sudo` inside Alpacon, turn off **Sudo outside the web terminal**. See [External access](/use/audit/governance/external-access/).

## What is recorded

- **Terminal sessions**: Websh sessions are recorded, with credentials masked. On a paid plan you can replay a whole recording; on the Free plan you see only its opening. See [Session recordings](/use/audit/sessions/).
- **Commands**: each command with its requester, session, AI judgment and output. See [Commands](/use/audit/events/commands/).
- **File transfers**: each upload and download, including refused ones, with its session.
- **sudo**: each allowed and refused `sudo`, with the reason. See [Privilege elevation](/use/audit/events/sudo/).
- **Approvals**: who asked, who decided, when, and whether it was self-approved.
- **AI analysis**: a completed, expired or revoked session gets an AI risk analysis of what took place. See [After a session](/use/audit/sessions/review/).
- **Direct logins**: when detection is on, logins that bypassed Alpacon.

Audit records are read-only. How far back you can look depends on your plan; see the [pricing page](https://www.alpacax.com/alpacon/pricing).

## Known limits

- **The AI's judgment is the main per-command check.** When it is unavailable, session commands run marked **Skipped**, and only rules that don't depend on the AI still hold them.
- **Terminal commands aren't judged one at a time.** In a Websh terminal only `sudo` is judged as it runs; the rest is recorded and analyzed after the session. Agents can't open a terminal.
- **Advisory turns off holds.** In an Advisory workspace, nothing is held or refused because of a judgment, and sessions are admitted without approval.
- **Service tokens work without a session**, within their own limits. A service token's command the AI rejects still runs unless it is rated Critical.
- **Direct logins aren't blocked.** Detection is off by default and records only.
- **The agent's name is self-reported.** See [What Alpacon checks, and what it doesn't](/learn/security/what-alpacon-checks/#known-limits).
- **Self-approval is allowed by default.** Forbid it in the rule where it matters.
- **A delivered command runs to the end.** Ending a session cancels commands not yet delivered; one already running on the server is not stopped.
- **Alpacon is not a sandbox or an EDR.** It controls who reaches a server and what they run through Alpacon; it doesn't contain what a permitted command does on the server.

Source: https://docs.alpacax.com/learn/security/session-protection/
