What counts as a secret

Reading · 5 min · Module 6, lesson 1 of 541 min left in this module

Module 6 · SecretsLesson 1 of 5

Goal: Sort an app's configuration values into secrets and ordinary settings, and say why each one belongs where it does.

Key idea

A secret is any value that lets whoever holds it act as you or your app: sign in, read data, spend money, or pass as your server. Ask one question of every value: if a stranger had this, could they do something they shouldn't? If yes, it's a secret.

What usually is a secret

Module 4 moved configuration out of the code. Some of that configuration needs more care than the rest:

  • Passwords: for a database, a mail server, an admin account.
  • API keys and access tokens: anything a provider gives you to prove a request comes from you, such as a payment or email service key, or a personal access token for GitHub.
  • Private keys: the private half of a TLS certificate, an SSH key, a key that signs files or releases.
  • Signing secrets: the value your app uses to sign session cookies or login tokens, or to check that a webhook (a request a provider sends your app when something happens, such as a payment) really came from that provider. Anyone who has it can forge them.
  • Connection strings with a password in them: postgres://app:[email protected]:5432/shop is a secret because of the part between : and @.

What usually isn't

  • Addresses without credentials: https://api.example.com, or a database host name on its own.
  • Feature flags and tuning: NEW_CHECKOUT=on, LOG_LEVEL=info, a page size.
  • Public keys: the public half of a key pair, or a certificate. They're meant to be handed out.
  • Keys a provider says are safe in a browser: some services issue a second, limited key for front-end code. Their documentation says so explicitly. If it doesn't, assume the key is secret.

These are still configuration, so they still live outside the code. They just don't need hiding.

The grey areas

Mixed values. A connection string mixes an address with a password. Many teams keep the whole string secret, which is the safe default. Others split it into DATABASE_HOST (a setting) and DATABASE_PASSWORD (a secret).

Internal names. An internal host name or account ID won't let anyone in, but it helps an attacker map your system. Don't publish it, but it doesn't need secret storage either.

When in doubt, treat it as a secret. Hiding a value that didn't need it costs you a little convenience. Exposing one that did can cost you your data.

Why the difference matters in practice

Secrets and settings get different handling from here on:

  • A secret can't be shown back to you once it's stored, on ComputeSphere or most other platforms (lesson 2.6.4). A setting can, which makes it easy to check.
  • A leaked secret has to be rotated: replaced with a new value and the old one switched off. A leaked feature flag is just a curiosity.
  • Secrets never go in front-end build variables such as NEXT_PUBLIC_… or VITE_… (lesson 2.4.3), because those end up in files every visitor downloads.

Check yourself

Which of these is a secret?
A teammate says the TLS certificate and its private key are both secrets. Are they right?

In the docs