Most AI agent breakouts are not zero-days. They are file permissions, sudo rules, and mounts that were too generous.

Least privilege means: the agent gets the exact files, commands, and network it needs, nothing else, for the shortest time possible. Here is how to apply that on Linux.

Quick Answer: What Does Least Privilege Mean for an AI Agent?

Give the agent its own Linux user with no sudo, ownership of exactly one work directory, and read-only mounts everywhere else. Allow at most one named privileged command via sudoers, drop all container capabilities, and re-check permissions every time you add a tool. If the agent can read your SSH keys or publish packages, the boundary is already wrong.

Key takeaways:

  • Default deny, then allow named commands. NOPASSWD ALL is root with extra steps.
  • Permissions rot with every new tool. Re-audit on every capability you grant.
  • Five systemd lines (User, NoNewPrivileges, ProtectHome, PrivateTmp, ProtectSystem) confine a service agent with no container needed.

Linux users and file modes control the blast radius

Create a dedicated account and check what it can actually read:

sudo useradd -r -s /bin/false -m agent-runner
ls -l ~/.ssh/ 2>&1 | head -3
sudo -u agent-runner cat ~/.ssh/id_rsa 2>&1 | head -1
sudo -u agent-runner id

The cat as agent-runner should fail with Permission denied. If it succeeds, your home directory or key permissions are too open. Fix with chmod 700 ~ and chmod 600 ~/.ssh/*, and never store keys inside the agent workspace.

Sudo rules: default deny, allow specific commands

If the agent needs one privileged command, allow only that command, not full sudo:

# /etc/sudoers.d/agent-runner - edit with visudo
agent-runner ALL=(root) NOPASSWD: /usr/bin/systemctl status *
# Verify - this should work, anything else should fail
sudo -U agent-runner -l

Avoid agent-runner ALL=(ALL) NOPASSWD: ALL. That is root with extra steps. Ubuntu documents sudo and permissions in its server security guide.

Set ownership so the agent cannot wander

Ownership is the part people skip. The agent directory should belong to the agent account, and nothing else should be writable by it:

sudo chown -R agent-runner:agent-runner /srv/agent-work
sudo chmod 750 /srv/agent-work
ls -ld /srv/agent-work
# Agent writes here, but cannot write to /srv, /etc, or your home

Check effective access with sudo -u agent-runner bash -c 'touch /srv/agent-work/test && rm /srv/agent-work/test && echo writable' and confirm the same user cannot write outside that tree. If your agent runs as a systemd service, add confinement directly in the unit:

[Service]
User=agent-runner
NoNewPrivileges=yes
ProtectHome=yes
PrivateTmp=yes
ProtectSystem=strict
ReadWritePaths=/srv/agent-work

Those five lines block privilege escalation, hide home directories, and limit writes to one path. Test the service with systemd-analyze security agent.service and fix any red findings before giving the agent real tools.

Audit the boundary before you grant anything new

Permissions are set once and forgotten while tools keep accumulating. Before granting anything, check what the agent can already reach. These three commands take a minute and usually surprise people:

# What can the agent read outside its directory?
sudo -u agent-runner find /home /root /etc -readable 2>/dev/null | head -20

# What sudo does it actually have?
sudo -U agent-runner -l

# Files anyone can write (a classic breakout helper)?
find /srv/agent-work -type f -perm -o+w 2>/dev/null

Anything in the first list that is not the work directory is a finding. Fix ownership and modes first, then grant the new tool the narrowest path that makes it work, and re-run the same three commands to confirm nothing else opened up.

Sandboxing layers that actually help

  • Docker with dropped capabilities: --cap-drop ALL --read-only --user UID:GID plus read-only mounts. See our walkthrough in Build a Sandboxed AI Agent on Ubuntu Using Docker.
  • systemd confinement: if you run the agent as a service, set NoNewPrivileges=yes, ProtectHome=yes, and PrivateTmp=yes in the unit file.
  • AppArmor / SELinux: use the default Docker AppArmor profile. Do not disable it to fix a permission error.

Separate secrets from workspaces

Agents copy whatever they can see into prompts and logs. Keep tokens out of the mounted directory. Use environment files readable only by root, or a credential proxy, and scope tokens so a leak does not give publish rights. Our Git abuse protection guide shows the same idea for GitHub tokens.

FAQ

Is running as non-root inside Docker enough? No, if you also mount the Docker socket or host root. Non-root plus no sensitive mounts is what matters.

What about capabilities? Start with none. Add back only the one capability a failing tool needs, for example --cap-add NET_BIND_SERVICE to bind a low port.

How often should I review permissions? Every time you add a tool to the agent. New tools usually ask for broader files and network than they need.

How do I find files the agent should not see? Run sudo -u agent-runner find /home /root -readable and treat every hit as a bug. Pay special attention to SSH directories, cloud credential files, and shell history.

Should I use SELinux or AppArmor profiles for agents? Keep the defaults on and write narrow exceptions instead of disabling them. The afternoon you spend on one profile beats the incident review after a breakout you could have contained.

What to read next

Pair this with How to Secure AI Agents Running on Linux for the overview and What Happens When an AI Agent Gets Root Access to see why root is different. For log monitoring, see AI-Powered Linux Security Monitor.

External resources

Related Tools

Try these companion tools on DevStackIO Tools: