Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Keep API keys out of code

After this lesson: I can keep a key out of my code and my Git history.

60 min lesson3 commandsAI coding agent lab: use opencode to explain and fix code, and check its work

A leaked API key costs money

An API key is a secret string that proves a request comes from you. A model provider often charges your account for every call that carries it.

Developers leak keys by typing them into code and pushing it to Git. Automated scanners look for exactly that, so a leaked key is a bill and a risk.

By the end of this lesson

Note

I can keep a key out of my code and my Git history.

Key words

WordWhat it meansExample
API keya secret string that proves a request is yours
Environment variablea named value given to a program from outside its codeMY_API_KEY
The .env filea text file of NAME=value lines for your own machine
The .gitignore filea list of files Git must never track
Rotateto make a new key and cancel the old one

The cells students fill in are left blank in this preview.

In this lab your code holds no key

Your script sends the header authorization: Bearer lab. The word lab is a placeholder, not a key. On its way out, the platform swaps it for your real token and picks the model.

So the key is never in your code and you never see it. On a real project, you hold the key yourself.

Call a model with no key

Command
docker exec -w /home/node/project agent node -e "const u=(process.env.AI_URL||'http://ai:4000')+'/v1/chat/completions';(async()=>{const headers={'content-type':'application/json',authorization:'Bearer lab'};console.log('Authorization header in my code: '+headers.authorization);try{const r=await fetch(u,{method:'POST',headers,body:JSON.stringify({model:'lab',messages:[{role:'user',content:'In one sentence, why must an API key stay out of code?'}],max_tokens:60})});const j=await r.json();if(r.ok===false)throw new Error(r.status+' '+j.error.message);console.log('Model: '+j.choices[0].message.content)}catch(e){console.log('No answer from the model ('+e.message+'). Recorded sample:');console.log('Model: Anyone who can read the code can use the key and spend your money.')}})()"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A real key lives in the environment

A real provider gives you a long key. Never type it into a file Git tracks. Put it in an environment variable, and read it in code with process.env.MY_API_KEY.

On your own machine, keep the variables in a .env file and list that file in .gitignore, so Git never sees it.

Write a demo .env and .gitignore

Command
docker exec -w /home/node/project agent sh -c "mkdir -p keys-demo && printf 'EXAMPLE_API_KEY=not-a-real-key-123\n' > keys-demo/.env && printf '.env\n' > keys-demo/.gitignore"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Read the .env and hide the value

Command
docker exec -w /home/node/project agent node -e "const fs=require('fs');const nl=String.fromCharCode(10);for(const line of fs.readFileSync('keys-demo/.env','utf8').trim().split(nl)){const i=line.indexOf('=');const v=line.slice(i+1);console.log(line.slice(0,i)+' is set, '+v.length+' characters, value hidden')}console.log('.env is in .gitignore: '+fs.readFileSync('keys-demo/.gitignore','utf8').split(nl).includes('.env'))"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

The same idea in a real deployment

Your hosting service has a place for secrets and sets them as environment variables for your program. The code stays the same on your laptop and on the server.

Commit a .env.example file with the names and fake values. It tells a new teammate what to set.

Worked example: what to do after a leak

What happenedWhat to do
The key is in code, not committedMove it to an environment variable
It is committed, not pushedRotate the key, then rewrite the commit
It is pushed to a public repositoryRotate the key at once, then clean the history
It was pasted into a chat or a promptRotate the key

The cells students fill in are left blank in this preview.

A common mistake

Warning

Many people think deleting the key in a new commit removes it. Git keeps every old commit, so the key stays in the history for anyone who copied it. Rotate the key, because only a new key makes the old one useless.

About this lab and its source: AI coding agent lab: use opencode to explain and fix code, and check its work

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.