Lesson 3 of 6 · 15 min · Checked on 10 October 2026
Security in depth: sandbox, supply chain and auditing
By the end of this lesson you will be able to:
- Explain what a sandbox isolates: the folder, the network and the rest of the system
- Choose the right sandbox and permission mode in Codex and in Claude Code
- Defend a project against fake packages with pinned versions, reading what gets installed and pip-audit
- Leave a record of what the agent did, so you can audit it later
Rui builds the school website in his spare time. He asked the agent to “make the PDF sending work”. The agent installed three packages, the sending worked and Rui made a commit. One of the names had a letter swapped compared with a well-known package. Nobody noticed. This case is made up, but the pattern exists and has a name.
None of this is a reason to panic. It is a reason for three habits: knowing where the agent can touch things, knowing what comes into the project, and knowing, afterwards, what happened.
The concept: permissions, sandbox and record
Permissions decide when the agent asks. The sandbox decides what its commands can do, even when nobody asks. They are different layers, and you want both.
A sandbox isolates three things:
- the folder: where it can write;
- the network: whether it can connect to the internet, and to which sites;
- the system: what it can read from the rest of the computer, such as keys and settings.
The record is the third layer: when something goes wrong, it tells you what, when and why.
How it is done today: Codex
This is how it looks on 6 October 2026; your screen may differ. Look for the button with the same name. Guide: learn.chatgpt.com/docs/agent-approvals-security.
Codex has two pieces. The sandbox (--sandbox) has three modes: read-only, workspace-write and danger-full-access. The approval (--ask-for-approval) says when it asks: on-request asks when it needs to step outside the limits, never never asks.
The usual choice is workspace-write with on-request: it writes in the folder, with no network, and asks before leaving. Even so, the .git and .codex folders inside the project stay read-only. If a task really needs the network, turn it on in the configuration file with network_access = true, in the [sandbox_workspace_write] section. /permissions changes the mode and /status shows what is active.
How it is done today: Claude Code
The permission modes are: Manual (default), acceptEdits, plan, auto, dontAsk and bypassPermissions. The deny rules block in all of them. Guide: code.claude.com/docs/en/permission-modes.
The sandbox comes switched off. Turn it on with /sandbox. Guide: code.claude.com/docs/en/sandboxing. With it on:
- commands only write in the project folder and in temporary folders;
- the network goes through a filter, and the list of allowed sites starts empty;
- commands still read almost the whole computer. To close folders like
~/.ssh, usefilesystem.denyRead.
The sandbox applies to commands (Bash). Reading, editing and going on the web follow the permission rules. On Windows without WSL2 there is no sandbox; on Linux it needs two programs, bubblewrap and socat.
Watch out
Modes with no questions and no sandbox (bypassPermissions in Claude Code, danger-full-access with never in Codex) are only for virtual machines or disposable containers, as in lesson 1/06. Turning one of these on “just this once” on your own computer is exactly the moment it goes wrong.
The dependency chain
Every pip install brings in someone else's code, which runs with your rights. Two risks show up a lot:
- Typosquatting: someone publishes a package with a name almost identical to a well-known one and waits for a typing mistake.
- Made-up names: the model sometimes suggests a package that does not exist. If someone registers that name later with malicious code, the next person who follows the suggestion installs it. Some people call this “slopsquatting”.
The defences are simple:
- Read what the agent installs. Put
"Bash(pip install *)"in theasklist of.claude/settings.json, so it always asks. The rule is literal: it does not catchpython -m pip install,pip3 installoruv pip install. Add one rule for each form the agent uses, or ask it to always install withpip install. - Install only what you know. New package? Open its page on PyPI: the exact name, the linked project, the version history.
- Pin the versions.
python -m pip freeze > requirements.txtrecords each package with==. To go further, pip accepts--require-hashes. - Audit.
pip-auditcompares your dependencies with a database of known vulnerabilities:
python -m pip install pip-audit
pip-audit -r requirements.txt
If it finds nothing, it says “No known vulnerabilities found” and exits with code 0; if it finds something, it exits with 1. That is why it fits in a CI workflow, as in lesson 02.
Tip
pip-audit only knows problems that have already been recorded. A fake package published yesterday slips past it. Reading what gets installed is still the first defence.
Record and audit
- Git is the first record. Small commits, one per change.
git log --statshows what changed in each one. - A hook saves the commands. This example from the official guide, in
.claude/settings.json, appends each Bash command to a file. It needs thejqprogram.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.command' >> ~/.claude/command-log.txt"
}
]
}
]
}
}
- In Codex,
codex exec --jsonwrites each step as JSON lines, which you can save to a file.
Tip
Claude Code's conversations stay on your computer and are deleted after a while; the cleanupPeriodDays setting changes the period. If you need to keep a record, do not count on them: use the hook.
And the rule from lesson 1/06 does not change: secrets never go in the request or in the repository.
Exercise
In a disposable folder, experiencias/seguranca (“experiments/security”), with Git:
How I know it worked the agent asked for authorisation before installing, requirements.txt has == on every line, pip-audit gave a result (clean or with a list) and the log shows the commands the agent ran.
If it didn't work
- The agent installed without asking: check the quotes and the comma in the rule and open a new session;
/permissionsshows whether it was read. Also look at the command in the log: if it waspython -m pip installorpip3 install, the rule does not cover it; add a rule for that form. - The log is empty:
jqis missing, or the hook was not read./hooksshows the active hooks. pip-audit: command not found: the virtual environment where you installed it is not active.
Videos
In the specified section: why letting an AI agent run directly on your system is risky (installing things, reading and exfiltrating files, prompt injection) and how to isolate it in a Docker container without root.
Supply chain attacks on npm and how to stop them: SLSA, checking for known vulnerabilities, SBOM and Cosign.
Test what you learned
Corrections to this lesson (1)
- : After a second external review: the `Bash(pip install *)` rule is literal and does not catch `python -m pip install`, `pip3 install` or `uv pip install`; the lesson and «If it did not work» say so.