Skip to content
← Inforjota
Cursos Inforjota Português

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, use filesystem.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:

  1. Read what the agent installs. Put "Bash(pip install *)" in the ask list of .claude/settings.json, so it always asks. The rule is literal: it does not catch python -m pip install, pip3 install or uv pip install. Add one rule for each form the agent uses, or ask it to always install with pip install.
  2. Install only what you know. New package? Open its page on PyPI: the exact name, the linked project, the version history.
  3. Pin the versions. python -m pip freeze > requirements.txt records each package with ==. To go further, pip accepts --require-hashes.
  4. Audit. pip-audit compares 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 --stat shows 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 the jq program.
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.command' >> ~/.claude/command-log.txt"
          }
        ]
      }
    ]
  }
}
  • In Codex, codex exec --json writes 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; /permissions shows whether it was read. Also look at the command in the log: if it was python -m pip install or pip3 install, the rule does not cover it; add a rule for that form.
  • The log is empty: jq is missing, or the hook was not read. /hooks shows the active hooks.
  • pip-audit: command not found: the virtual environment where you installed it is not active.

Videos

Pare de expor seu SO para IA. Solução docker pronta!
Otávio Miranda · 29 min · PT-BR · subtitles · Watch on YouTube
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.
NPM Supply Chain Attacks Explained (And How To Stop Them)
DigitalOcean · 10 min · EN · subtitles · Watch on YouTube
Supply chain attacks on npm and how to stop them: SLSA, checking for known vulnerabilities, SBOM and Cosign.

Test what you learned

1. To fix an error, the agent proposes installing a package you have never heard of, with a name close to a well-known package. What do you do?
2. You turned on Claude Code's sandbox. A colleague says that now the agent “can no longer read anything outside the folder”. What is the right answer?
3. A script of yours runs Codex at night and needs to download a page. What is the safest choice?

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.