---
title: "Allow commands with a service token"
description: "Add command rules for an application service token, check sudo behavior, and recover when risk verification or an access rule refuses an automated command."
---

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

# Allow commands with a service token

<span id="command-patterns-and-sudo" />

Configure the token's allowed commands before running an automated job. [Token command matching](/reference/tokens/command-patterns/) explains the exact comparison rules and refusal codes.

## Write the rule exactly as you run it

Because the rule is compared against the line you submit, not the command that runs as root, a rule for a privileged command has to contain `sudo`.

| Command you run | Rule that allows it | Rule that does not |
| --- | --- | --- |
| `sudo systemctl restart nginx` | `sudo systemctl restart nginx` | `systemctl restart nginx` |
| `sudo -n systemctl restart nginx` | `sudo -n systemctl restart nginx` | `sudo systemctl restart nginx` |
| `sudo docker ps` | `sudo docker *` | `docker *` |

`sudo X` and `sudo -n X` are different command lines, so each needs its own rule. Register the line your pipeline actually runs: if a job adds `-n` for non-interactive use or `-u` to run as another account, that flag is part of the line being compared.

### Why wildcards with sudo are dangerous

A rule of `sudo *` grants unrestricted root access. Wildcards match across quoting, so that rule also allows `sudo bash -c "rm -rf /"`. `sudo bash -c *` and `sudo sh -c *` have the same effect.

List the exact privileged commands instead:

```
sudo systemctl restart nginx
sudo systemctl reload nginx
```

## What happens when a token runs sudo

Passing the allowed-command rule only gets the command delivered. Elevation is decided again on the server, at the moment `sudo` runs.

**Service tokens on Alpacon Cloud.** The workspace sudo setting must be on; otherwise sudo is refused with `workspace_sudo_with_mfa_disabled`. In Advisory, service-token sudo is not refused for risk at any level and the decision is recorded. Outside Advisory, once the command clears its allowed-command rule, elevation is decided automatically from the command's assessed risk: allowed at every level below Critical, refused at **Critical** with `SUDO_RISK_DENIED`. When AI verification rejected the command, the stricter of its overall risk level and the level the rejection was made at decides, so a command rejected as Critical is refused even when its overall level reads lower. A command that could not be assessed is allowed too, so an outage in risk assessment does not stall the pipeline. Nothing waits for a reviewer: a pipeline runs unattended, so nobody would be there to answer an approval prompt. Automatic elevations, including Advisory decisions, are recorded in [Privilege elevation](/use/audit/events/sudo/) against the application that owns the token.

**A command a person approved.** A service token command bound to a work session can be held for a person to approve (see [below](#what-happens-when-a-tokens-command-fails-ai-verification)). Once a person approves the held command, that approval covers the `sudo` written in the approved line: elevation is allowed at any risk level, Critical included, and the grant is recorded in [Privilege elevation](/use/audit/events/sudo/) as **Admin approval**, linked to that decision. Only an approval policy your workspace wrote to deny the command, or to require more than one approver, still applies.

**Sudo policies do not apply to a service token.** A sudo policy targets Alpacon users, and a service token is not one. Writing a policy will not change the outcome above.

**Administrators can tighten this outside Advisory.** A workspace `token_exec` rule can require refusal at a lower risk level than Critical—for elevation and for [AI-rejected commands](#what-happens-when-a-tokens-command-fails-ai-verification) below, since both read the same policy. It cannot make a token wait for a human reviewer.

**There is no sudo permission to grant.** No resource offers a `sudo` action in the token scope catalog, so elevation is not something you enable on the application's role or on the token's scopes. The allowed-command entry and the command's assessed risk decide it.

**API access tokens are different.** A personal API access token cannot elevate on its own. Run the command inside a [work session](/use/work-sessions/) that includes the sudo scope and is covered by a sudo policy, or move the workload to a service token.

On self-hosted deployments, `sudo` from a service token is refused with `SUDO_COMMAND_NOT_AUTHORIZED` because it cannot be tied to a person. Rerun it as a signed-in person's authorized command, or in a work session whose sudo policy matches the command.

## What happens when a token's command fails AI verification

Every command is checked by Alpacon's AI risk verification before it runs. Sent by a person, or inside a [work session](/use/work-sessions/), a command the verdict rejects is normally held so a person can let it run anyway. See [Verification status](/use/audit/events/commands/#verification-status) in Commands.

**A service token command sent with no work session skips that hold**—this is how CI jobs and other unattended automation run, and there's nobody to answer it. When the AI verdict rejects such a command, your workspace's token execution policy settles it on its own, the moment the verdict lands:

- At **Critical**, or at any level your policy refuses, the command is rejected with the result *Command rejected by AI verification*. Any commands chained to run after it are cancelled too, each with the result *Cancelled: prior command rejected*.
- Below that line, the command runs anyway. The rejection is recorded under **Rejected by verification, but executed via a session-less service token**, with the risk it was judged at. This label identifies the service-token path separately from signing monitor mode. See [Verification status](/use/audit/events/commands/#verification-status).

**Administrators can tighten this.** It's the same policy that already decides [token sudo](#what-happens-when-a-token-runs-sudo): lower the risk level it refuses at, and both this gate and elevation get stricter together. It cannot bring back the hold for a human reviewer.

A service token command bound to a work session, and any command from an existing personal [API access token](/use/settings/api-tokens/), keep the hold. File operations aren't affected—only executed commands go through this gate.

## When elevation is not available

If `sudo` is refused because it cannot be tied to a person, rerun it as a signed-in person's authorized command or in a work session whose sudo policy matches the command. If the command is assessed Critical or you need an alternative for automation, consider these options.

- **Remove the need for sudo.** Give the account the token runs as direct control of what it manages—a systemd user unit for the service, or membership in the group that owns the files. Nothing is elevated, so nothing has to be approved. This is the narrowest option and the one to try first.
- **Run inside a work session.** A work session with the sudo scope keeps the approval and audit trail intact. The trade-off is that a person has to request the session, so the deployment is no longer fully unattended.
- **Grant the command in the host's own sudoers file.** The job keeps running unattended, but that host's elevation is decided outside Alpacon: those commands do not appear in [Privilege elevation](/use/audit/events/sudo/) and no policy or approval applies to them. Treat this as a last resort, and only for a host you have deliberately excluded from Alpacon's privileged-access controls.

## Rule matching reference

The [token command matching reference](/reference/tokens/command-patterns/) covers wildcards, account and group matching, sudo-policy comparisons, and denial codes.

<span id="how-a-command-rule-is-matched" />
<span id="a-trailing-wildcard-needs-an-argument" />
<span id="username-and-group-on-a-rule" />
<span id="command-rules-and-sudo-policies-are-opposites" />
<span id="denial-messages" />

## Related docs

- [Service tokens](/use/iam/applications/service-tokens/)
- [Token command matching](/reference/tokens/command-patterns/)
- [Privilege elevation](/use/audit/events/sudo/)
- [sudo with MFA](/use/work-sessions/terminal/sudo-with-mfa/)
- [Commands](/use/audit/events/commands/)

Source: https://docs.alpacax.com/use/iam/applications/service-tokens/command-patterns/
