What is a "Secret"?

In application development, a secret is any piece of sensitive information that grants access or special privileges. This includes:

  • Database credentials (username, password, connection string)
  • API keys for third-party services (Stripe, SendGrid, AWS)
  • JWT secrets or other symmetric keys
  • Private certificates (e.g., for TLS/SSL)

These secrets are the keys to your kingdom. If they are compromised, an attacker could gain complete control over your application, steal user data, or incur massive financial costs.

The Cardinal Sin: Hardcoding Secrets

The single worst thing you can do is hardcode secrets directly into your source code.

What NOT to do:

JavaScript


// HORRIBLE PRACTICE - DO NOT DO THIS!
const dbConfig = {
  host: 'prod.database.server.com',
  user: 'myuser',
  password: 'MySuperSecretPassword123!', // Secret is hardcoded
  database: 'main_db'
};

const STRIPE_API_KEY = 'sk_live_fAkeKeYfRomGithuB12345'; // Secret is hardcoded

Why is this a disaster?

  1. It will be committed to version control (Git). Even if your repository is private, this massively expands the number of people who can see the secret. If the repository is public, you've just leaked your credentials to the entire world. Bots are constantly scanning GitHub for exactly this pattern.
  2. It's impossible to rotate. If a key is compromised, you have to change the code, commit it, and redeploy your entire application just to update a password.
  3. It prevents environment separation. You cannot use a different database password for your local development machine versus your production server.

Best Practice 1: Environment Variables for Local Development

The standard solution is to externalize secrets from your code using environment variables. For local development, this is easily managed with a .env file.

Step 1: Create a .env file In the root of your project, create a file named .env. This file will hold your secrets as key-value pairs.

.env:

Code snippet


# This is a comment
DATABASE_PASSWORD="MySuperSecretPassword123!"
STRIPE_API_KEY="sk_test_...your_test_key..."
NODE_ENV="development"

Step 2: Add .env to your .gitignore This is the most critical step. You NEVER want to commit your secrets to Git. Open your .gitignore file and add a new line.

.gitignore:

Code snippet


# Dependencies
node_modules/

# Secrets - DO NOT COMMIT
.env
*.env

Step 3: Use the dotenv package In your Node.js application, install the dotenv package (npm install dotenv). Then, at the very top of your main application file, load it.

index.js:

JavaScript


// Load environment variables from .env file
require('dotenv').config();

// Now you can access your secrets safely via the 'process.env' object
const dbConfig = {
  host: process.env.DB_HOST, // You would add DB_HOST to your .env
  user: process.env.DB_USER,
  password: process.env.DATABASE_PASSWORD, // Accessing the secret
  database: process.env.DB_NAME
};

const STRIPE_API_KEY = process.env.STRIPE_API_KEY;

console.log(`Running in ${process.env.NODE_ENV} mode.`);

Best Practice 2: Managing Secrets in Production

.env files are great for local development, but they are not a production solution. In production, you should use the secret management tools provided by your hosting platform or infrastructure.

Whether you're using Vercel, Heroku, AWS, Google Cloud, or Kubernetes, they all provide a secure dashboard or CLI command to set environment variables. These variables are then injected into your application's environment at runtime. This keeps your secrets out of your codebase and build artifacts.

Best Practice 3: Secrets Vaults (Advanced)

For applications with very high security requirements, a dedicated secrets management platform (or "vault") is the best approach. Tools like HashiCorp Vault, AWS Secrets Manager, and Google Secret Manager provide:

  • Centralized, encrypted storage for all secrets.
  • Fine-grained access control and policies (e.g., this server can only access the database password).
  • Dynamic secrets that are generated on-demand and have a short lifespan.
  • Automatic rotation of credentials.
  • Detailed audit logs of who accessed what secret and when.