Area 06 // AI SecurityLesson 97 / 14015 min read
Least-privilege tools and sandboxing
Least privilege means giving an AI agent only the tools, permissions and data it needs for its job (read-only where possible, narrow scopes, short-lived credentials), and sandboxing means running anything risky, such as model-written code or shell commands, in an isolated environment where mistakes and attacks can't reach real systems.
Think of it like this
Analogy
A hotel gives the cleaner a key card that opens guest rooms on one floor during working hours, not the safe, the office or the whole building. If the card is lost or misused, the damage is small. And when a guest wants to try something risky, like a cooking class, it happens in the training kitchen, not the restaurant's kitchen during dinner service.
Key cards are least privilege; the training kitchen is the sandbox.
The problem it solves
Agents call tools, and tools touch real systems: databases, files, email, cloud accounts, shells. If the model is confused or prompt-injected, it will happily use every capability you gave it. An agent holding an admin database connection, your cloud keys and a shell is one clever web page away from disaster. OWASP calls this excessive agency, third on the 2026 list.
How it works: least-privilege tools
- List each tool's worst case: if a hostile actor controlled the model, what could this tool do?
- Make tools narrow:
get_order_status(order_id)instead ofrun_sql(query);send_reply(ticket_id, text)instead ofsend_email(to, body). Narrow tools are also easier for the model to use correctly (tool calling). - Minimal permissions in the system itself: read-only database users or connections, API tokens with narrow scopes, file access limited to one folder.
- Act as the user, not as a superuser: the agent's credentials carry the end user's identity and permissions, so it can never see more than the user could (agent authorization).
- Short-lived credentials: tokens that expire in minutes, issued per task, never long-lived keys in the agent's context (secrets).
- Validate arguments in code: IDs belong to the user, amounts within limits, paths inside allowed folders.
- Remove what isn't used: review tool lists regularly; every tool is attack surface.
How it works: tool sandboxing
- Anything that runs code or commands (code interpreters, coding agents, shell tools, browser automation) runs in a sandbox.
- Isolation level: a separate process is the minimum; containers are common; microVMs (e.g. Firecracker, gVisor-style kernels) or hosted sandboxes give stronger isolation for untrusted code (Docker).
- Nothing worth stealing: no production secrets or environment variables, a throwaway filesystem with only the files the task needs.
- Network rules: no network, or an allow-list (e.g. a package mirror only), to stop data exfiltration.
- Resource limits: CPU, memory, disk, process count and wall-clock time.
- Destroy after use: a fresh sandbox per task or session; copy out only the results (a diff, a file) for review.
- Log commands and outputs for audit.
See it in code
- Needs
- Nothing: plain Python 3 (sqlite3 and subprocess are built in). A separate process is the lightest sandbox; production uses containers or microVMs.
A read-only database tool that SQLite itself protects, and model-written code run in a separate process with no environment variables, a temporary folder and a timeout.
import os, sqlite3, subprocess, sys, tempfile
# LEAST PRIVILEGE: the agent's "query orders" tool opens the database READ-ONLY.
db = os.path.join(tempfile.mkdtemp(), "shop.db")
with sqlite3.connect(db) as con:
con.execute("CREATE TABLE orders (id INTEGER, status TEXT)")
con.execute("INSERT INTO orders VALUES (1, 'shipped')")
def query_orders(sql: str):
con = sqlite3.connect(f"file:{db}?mode=ro", uri=True) # read-only connection, enforced by SQLite
try:
return con.execute(sql).fetchall()
except sqlite3.OperationalError as e:
return f"refused: {e}"
finally:
con.close()
print(query_orders("SELECT * FROM orders"))
print(query_orders("DELETE FROM orders")) # even if the model is tricked into this
# SANDBOXING (light version): run model-written code in a separate process with a timeout,
# an empty environment (no API keys) and a throwaway working directory.
code = "import os; print('keys visible:', [k for k in os.environ if 'KEY' in k]); print(sum(range(10)))"
os.environ["OPENAI_API_KEY"] = "dummy-not-a-real-key"
result = subprocess.run([sys.executable, "-I", "-c", code], capture_output=True, text=True,
timeout=5, env={"SYSTEMROOT": os.environ.get("SYSTEMROOT", "")},
cwd=tempfile.mkdtemp())
print(result.stdout.strip())[(1, 'shipped')]
refused: attempt to write a readonly database
keys visible: []
45The DELETE fails because the connection is read-only, not because anyone asked the model to behave. The child process can't see the parent's API key. A process still shares the machine's network and files, so for untrusted code use a container or microVM with networking off.
A real example
Example
The data-analysis agent that could drop tables
A startup's analytics agent answered business questions by writing SQL. In the prototype it used the app's main database connection. During a security review, someone asked it to "clean up the test data" and it deleted rows from a production table.
The fix: a read-only replica with a dedicated database user that could only SELECT from analytics views (no personal-data columns), query time and row limits, and generated Python charts executed in a container with no network and no credentials. The agent got slightly less flexible and a great deal less dangerous.
The easy way
Start here
Before adding a tool, write down its worst case. Use read-only credentials wherever the tool only reads, narrow the tool to a specific action, and never give an agent a shell or code execution outside a container with networking off and no secrets.
When you grow: the production setup
Platforms issue per-task, per-user short-lived credentials through a token service, define tools with explicit scopes and argument validation, run code in hosted sandboxes or microVMs with egress allow-lists and resource quotas, rebuild sandboxes per session, review tool inventories regularly, and test with adversarial evals that try to escalate privileges.
Trade-offs
What you gain
- Limits damage from injection, bugs and model mistakes.
- System-enforced permissions can't be talked around.
- Narrow tools are easier for models to use correctly.
What it costs you
When not to use it
- Never skip least privilege; you can relax sandbox strength for code you wrote and trust, but not for model-written code.
Common mistakes
Interview questions
Try answering out loud first, then open the model answer.
How do you apply least privilege to an AI agent?
Model answer
Inventory tools and their worst cases; replace general tools with narrow, task-specific ones; enforce permissions in the systems themselves (read-only users, scoped tokens, folder limits); have the agent act with the end user's identity and permissions; issue short-lived credentials per task; validate arguments in code; and remove unused tools. Pair with approvals for actions that change things.
How would you sandbox an agent that runs code?
Model answer
Run each task in a fresh, isolated environment (container or microVM depending on trust), with no secrets or production credentials, network disabled or allow-listed, CPU, memory, disk, process and time limits, only the needed files mounted, and destruction after use. Return only the results for review, and log commands and outputs.
Why aren't prompt instructions enough to keep an agent read-only?
Model answer
Instructions can be overridden by injection or misread by the model. If the underlying credential can write, eventually something will make it write. Enforcing read-only at the database or API level makes the restriction hold regardless of what the model is persuaded to do.
Quiz
Pick an answer to see whether it’s right and why.
0 of 5 answered
Key terms
- Least privilege
- Giving each user, service, tool or agent only the permissions it needs for its job, and nothing more, so mistakes and attacks can do little damage.
- Sandbox
- An isolated environment (container, VM, restricted process) where code or agents run with limited access, so mistakes and attacks stay contained.
- Excessive agency
- When an AI system has more tools, permissions or autonomy than its job needs, so a mistake or attack can do real damage. LLM03 in the OWASP 2026 list.
- Scoped credentials
- Keys or tokens limited to specific actions and resources (for example read-only access to one table), ideally short-lived.
- Container
- A lightweight, isolated package of an app and everything it needs to run, sharing the host's kernel. Docker is the most common tool. Also used as a sandbox.
Before and after
Progress is saved in this browser only.