Lesson 6 of 8 · 15 min · Checked on 6 October 2026
Secrets, permissions and spending caps
By the end of this lesson you will be able to:
- Keep a key in a .env file that Git ignores
- Act at once when a key leaks: revoke it and create another
- Set rules that tell the agent what it may do, what it must ask about and what it never does
- Turn on a blocking spending cap (and, if you like, alerts) in the provider's console before the first call with a key
The bakery owner's nephew wanted to put a map from a paid service on the page. He pasted the API key into the code, made a commit and sent everything to a public repository. The next day the account showed charges nobody at the bakery had made: someone had found the key.
What a secret is
A secret is anything that opens a door: your email password, an API key (the code a program uses to pay for a service) or a token. The provider can't tell whether it's you using it or someone else.
The golden rule: a secret never goes into the code, into a commit or into the conversation with the agent. The conversation is stored and passes through the provider. If you pasted a key there, treat it as exposed.
The concept: a safe and a list of what stays in
Secrets live in a file called .env (the dot is part of the name). The program reads it by the variable name. Another file, .gitignore, tells Git to leave .env out when you run git add. So the code goes to GitHub without the secret.
But .gitignore is not a lock: the agent, or any program of yours, can read .env. Nor does it hide a key that goes into the JavaScript the browser downloads, like the bakery map's key: anyone who opens the page can see it, .env or not. Those need other protections, which come later. So, during the course, use only the pretend key from the exercise.
How it's done today: .env and .gitignore
This is how it looks on 6 October 2026; your screen may differ. Look for the button with the same name.
In the project folder, first create .gitignore with this line:
.env
Only then create .env, with one line per secret:
API_KEY=paste-your-key-here
To the agent you say only the name:
The program should read the key from the API_KEY variable, which is in the .env file.
Do not read or show the contents of .env.
Watch out
The order matters. If .env goes into a commit before it's in .gitignore, the key stays in the history, even if you delete the file afterwards. And adding it to .gitignore afterwards does not take it out: Git keeps following what it already tracks. If that history goes to GitHub, the key is lost.
If a key leaks
In this order, now:
- Go into the provider's console and revoke the key: it stops working for anyone.
- Create a new key and put it in
.env. - Check the last few days' usage: did anyone use it?
- Only then clean up the code and the history, with the agent's help.
Tip
Create one key per project, named for its purpose (“padaria-map”): if it leaks, you revoke only that one.
Permissions: what the agent may do
Depending on the mode, the agent asks authorisation before certain actions. Rules save you repeated questions and forbid what must never happen. There are three lists:
- Allow: it does this without asking (running the tests).
- Ask: it always asks authorisation (sending to GitHub).
- Deny: it never does this, even if you ask (reading
.env).
In Claude Code, the rules live in .claude/settings.json, inside the project. This example from the official documentation forbids reading .env:
{
"permissions": {
"deny": ["Read(./.env)", "Read(./.env.*)"]
}
}
The ban always wins: deny rules are checked first. The /permissions command shows the active rules. Guide: Claude Code permissions.
In Codex, the sandbox decides where it may write and whether it uses the Internet; the approval policy decides when it asks. In Auto mode, it writes only in the folder, without network, and asks before going further. /permissions changes the mode; /status shows the active one. Permission profiles, still in testing, can also forbid reading .env. Guide: Codex approvals and security.
Tip
Writing “do not read .env” is a request; a deny rule is a lock enforced by the tool. But it only stops the agent, not a program it runs. So, while you are learning, keep no real keys in there.
The mode that doesn't ask
Both tools have a mode in which the agent does everything without asking: --dangerously-skip-permissions in Claude Code and --dangerously-bypass-approvals-and-sandbox in Codex. “Dangerously” is there on purpose.
Watch out
In that mode the agent can delete files, install programs and send data without asking. Use it only in an isolated environment, such as a virtual machine or a container, with a throwaway folder inside. A throwaway folder on your everyday computer isn't enough: without the protection, the agent walks out of it.
In Claude Code, recent versions may start in automatic mode, where another model approves for you. While you're learning, press Shift+Tab until you see manual mode on: Manual mode asks before most actions.
Spending cap: before the first call
With an API key, every request costs money. Before the first call, turn on the right control in the provider's console:
- blocking cap: when spending reaches the amount, requests are refused;
- alert: you get a warning, but requests carry on.
Always turn on the cap, at a low amount (raising it is easy); an alert below it gives you time to react. In the Anthropic console: Settings > Billing, Spend limits section. On OpenAI's: Spend, Edit spend limit, and turn on Enforce a hard limit (without it, requests are not refused). OpenAI warns that enforcement is not instant: spending can go slightly over the cap. Guides: Anthropic spend limits and OpenAI spend limits. Amounts for each plan: see the Current state page.
Exercise
In the padaria folder from lesson 5:
How I know it worked git status shows .gitignore as a new file and doesn't show .env. In Claude Code, the first request is blocked by the rule and the second one works. In Codex, /status shows that it can write only inside the project folder (or that it's read-only, if you have not yet trusted the folder).
If it didn't work
.envshows up ingit status:.gitignorehas a mistake in the name or in the line. On Windows, Notepad may save it as.gitignore.txt(turn on file extensions).- You can't see the files that start with a dot: they are hidden. In PowerShell,
dir -Forceshows them; on Mac, Linux and WSL,ls -a. .envalready went into a commit:git rm --cached .envtakes it out of Git without deleting it from the disk; then make a commit. If the key was real, revoke it anyway.- The agent read
.envdespite the rule: check the name.claude/settings.json, the commas and the quotes, and open a new session./permissionsshows whether the rule was read.
Videos
Shows how to keep passwords and API keys out of code using environment variables (with a Python example); it does not cover the spending limit.
An official Anthropic video on Claude Code's automatic mode: how the classifier filters each action and how to configure it.
Test what you learned
Corrections to this lesson (1)
- : After an external review: `.gitignore` is no longer presented as access control (the agent reads `.env`); a key that ends up in browser JavaScript is exposed, so only the fake key is used; «never goes into a commit» does not hold for files Git already tracks; the Windows command is now `dir -Force`; the spending cap matches lesson 2. Quiz options were reordered.