Basic

Keeping the key secret

I pasted the signing key in the source and pushed it. A secret in code is a secret in public. Read it from the environment so it never lands in the repo.

What you will see

no key

About 1 min of reading

Quick check

Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.

Try It

Move a secret out of source and into the environment.

1

Read the key from the environment. The repo never holds the value.

import os SECRET = os.environ['SIGNING_KEY'] print(len(SECRET) > 0)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
True
2

If the key is missing, fail loudly at boot, do not default to a constant.

import os if not os.environ.get('SIGNING_KEY'): raise SystemExit('no key')

Before you run it, say out loud what it will print. Then open the answer.

What it prints
no key
A default like SECRET = 'dev' is a real bug: it ships a known signing key to production. Fail at boot when the secret is absent, never fall back to a constant.

Put it in order

Before you write anything, put these lines back in the right order. Click a line to move it up one step. This support step is easier than writing code from scratch, and it is here to make the last example stick.

Data Flow

A secret is read from the environment at runtime, never written in source, and if it ever leaked to a repo the only fix is to revoke and rotate it.
1 Code names the secret
↓
2 Runtime supplies the value
↓
3 Missing key fails at boot
↓
4 Leaked secret is rotated
Line by line

Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.

import os sets nothing on screen
SECRET = os.environ['SIGNING_KEY'] sets nothing on screen
print(len(SECRET) > 0) True
Why this works
Secrets live outside code

A secret in source is in history, diffs, and every fork. Read it from the environment or a secrets file that is gitignored. The code names the secret; the runtime supplies the value. That split is the whole rule.

Rotate after a leak

If a secret ever reached a public repo, deleting the line is not enough, history still holds it. Revoke and issue a new value, then treat the old one as burned. Rotation is the fix, not deletion.

Examples

Hardcoded is public

SECRET = 'sk-live-9f2a...'   # in the file, in git, in the diff

A literal in source is visible to every reader of the repo. One push and the secret is public.

Read from env

import os
SECRET = os.environ['SIGNING_KEY']

The value lives in the environment, not the file. The repo holds the name, never the value.

Fail if missing

if not os.environ.get('SIGNING_KEY'):
    raise SystemExit('no key')

If the key is absent, stop at boot. A silent default is a secret shipped as a known constant.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Why the salt matters
Previous Lesson
Why the salt matters
Next Lesson
The page runs your input
The page runs your input →