A payment key on a public page
A developer at a small online shop shares some code to ask for help. Inside the file is the key to the shop’s payment account.
Within an hour, someone has found it and used it. Programs scan public code for keys all day long. The key should never have been in the file.
By the end of this lesson
Note
I can keep secrets out of code.
Key words
| Word | What it means | Example |
|---|---|---|
| Secret | a password, key or token that grants access | |
| API key | a secret a program uses to prove who it is | |
| Environment variable | a named value a program reads when it runs | SHOP_API_KEY |
| .gitignore | a file listing what Git must never save | |
| Validation | checking input against what is allowed |
The cells students fill in are left blank in this preview.
A secret in a file travels with it
Code gets copied: into Git, onto colleagues’ laptops, into chat messages, onto public sites. A secret written in the code goes everywhere the code goes.
Git also keeps every old version. Deleting the line later does not remove it from the history.
So the first job is to find secrets that are already there.
Try it: search code for secrets
mkdir -p shop && cd shop
printf 'API_KEY = "sk_live_51Hx9demo"\nprint("Taking payment")\n' > pay.py
printf 'print("Showing orders")\n' > orders.py
# Search every file for something that looks like a secret
grep -n -i "key\|password\|token" *.py
# Add a line with password = "hunter2" to orders.py and search again
Read secrets from the environment
Instead of writing the key in the file, the program reads an environment variable when it runs.
On a laptop, the value often sits in a file called .env. That file is listed in .gitignore, so Git never saves it. On a server, the value comes from a secrets store.
The code holds only the name of the variable, never the value.
Try it: a key from the environment
mkdir -p shop && cd shop
# The script reads the key from the environment, never from the file
printf 'echo "Key found, it ends in ${SHOP_API_KEY: -4}"\n' > pay.sh
# Set the variable for this session only, then run the script
export SHOP_API_KEY="demo-key-7731"
bash pay.sh
# The file itself holds no secret
cat pay.sh
# Try: export SHOP_API_KEY="another-key-0042", then run bash pay.sh again
Worked example: where each thing lives
| Thing | In the code? | Where it lives |
|---|---|---|
| The variable’s name, SHOP_API_KEY | Yes | In the code |
| The key on your laptop | No | A .env file listed in .gitignore |
| The key on the live server | No | A secrets store |
| An example value for colleagues | Yes | A .env.example file with a fake value |
The cells students fill in are left blank in this preview.
Check input against what is allowed
Secure code also distrusts its input. Validation checks every value before it is used.
Decide what is allowed and refuse everything else. A quantity should be a whole number from 1 to 99. Words, minus signs and 5,000 are all refused.
Check on the server too, because anyone can send a request without your form.
A common mistake
Warning
Many people think a private repository is a safe place for keys. Private code still gets cloned to laptops, shared and sometimes made public by mistake. Keep keys out of every repository, because you cannot control every copy.