Secure Secret Management and Environment Variables
Avoid hardcoded secrets in source code by using secrets managers (Vault, AWS Secrets Manager) and environment variable injection at runtime.
Secure Secret Management and Environment Variables is a free Cloud & IT Cert Prep lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Cloud & IT Cert Prep learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Hardcoded Secret Problem
Hardcoded secrets — API keys, database passwords, TLS private keys, and OAuth tokens embedded directly in source code — are one of the most common and preventable security vulnerabilities. Secrets in source code are exposed in version control history (even after deletion), visible to all developers with repository access, and frequently leaked when repositories are accidentally made public. Tools like GitGuardian and truffleHog continuously scan for leaked secrets on platforms like GitHub.
# DANGEROUS: hardcoded secret in source code
# db_password = 'P@ssw0rd#2026'
# api_key = 'sk-live-abc123xyz789'
# aws_secret = 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY'
# These secrets are now:
# - In git history (even if later deleted)
# - Visible to all repo contributors
# - Potentially in CI/CD logs
# - Often leaked when repos go public accidentallyEnvironment Variables: Better but Not Enough
Environment variables remove secrets from source code by injecting them at runtime through the host OS or container orchestrator. The application reads os.environ['DB_PASSWORD'] rather than a hardcoded value. This is better than hardcoding, but environment variables have weaknesses: they appear in process lists, are inherited by child processes, often end up in crash dumps and debug logs, and require manual rotation. They are appropriate for development but not sufficient alone for production secrets management.
# Environment variable pattern:
# In .env file (NEVER commit to git):
# DB_PASSWORD=P@ssw0rd#2026
# API_KEY=sk-live-abc123xyz789
# In .gitignore:
# .env
# *.env
# .env.*
# In application code:
# db_password = os.environ.get('DB_PASSWORD')
# api_key = os.environ.get('API_KEY')
# Risk: env vars visible in 'ps aux' output,
# inherited by child processes, appear in /proc/<pid>/environDedicated Secrets Managers
Secrets managers are purpose-built systems for storing, rotating, and auditing access to secrets. Leading solutions include HashiCorp Vault (open source and enterprise), AWS Secrets Manager, Azure Key Vault, and Google Cloud Secret Manager. Applications authenticate to the secrets manager at runtime, retrieve the secret, and use it — no secrets are ever stored on disk or in environment variables. All access is logged, enabling auditing of who accessed which secret and when.
# HashiCorp Vault secret retrieval (conceptual):
# Application authenticates to Vault using:
# - AWS IAM role (in cloud environments)
# - Kubernetes service account token
# - AppRole credentials
# After authentication, retrieve secret:
# vault kv get -field=password secret/prod/database
# In application (Python SDK):
# client = hvac.Client(url='https://vault.company.com')
# client.auth.aws.iam_login(role='prod-app')
# secret = client.secrets.kv.read_secret('prod/database')
# db_password = secret['data']['password']Automatic Secret Rotation
A key advantage of secrets managers over environment variables is automatic rotation. AWS Secrets Manager can automatically rotate RDS database passwords on a schedule (e.g., every 30 days) without requiring application redeployment. The secrets manager updates the password in the database and updates the stored secret simultaneously. Applications that retrieve secrets on each connection automatically receive the new credential. This eliminates the common practice of 'permanent' service account passwords that never rotate.
# AWS Secrets Manager rotation configuration:
# Secret: prod/app-database-credentials
# Rotation: enabled
# Frequency: every 30 days
# Lambda function: SecretsManager-MyRDSRotation
# Rotation process:
# 1. Lambda creates new DB password
# 2. Updates secret in Secrets Manager
# 3. Updates password on RDS instance
# 4. Tests new credentials work
# 5. Deprecates old credentials
# Application: always calls GetSecretValue at runtime -> gets fresh valueThe .gitignore Defense
The first line of defense against committed secrets is a properly maintained .gitignore file that excludes all files that could contain secrets. However, .gitignore only prevents future commits — secrets already committed remain in git history. If secrets are accidentally committed, they must be treated as compromised immediately: rotate the secret, then optionally use tools like git filter-repo to rewrite history (required for compliance but insufficient alone since the secret may already be extracted).
# Recommended .gitignore entries for secret files:
# .env
# .env.*
# *.pem
# *.key
# *.p12
# *.pfx
# credentials.json
# service_account*.json
# secrets.yaml
# config/secrets.yml
# terraform.tfvars (may contain cloud credentials)
# .aws/credentials
# Pre-commit hook to scan for secrets before commit:
# pre-commit install
# hook: detect-secrets / gitleaks / truffleHogInfrastructure as Code Secrets
Infrastructure as Code (IaC) files (Terraform, CloudFormation, Kubernetes manifests) frequently contain secrets — database connection strings, API keys in environment variable declarations, and TLS certificates. These files are often committed to version control, creating secret exposure risk. Solutions include Vault dynamic secrets (Vault generates a short-lived credential specifically for each Terraform run), Kubernetes Secrets (stored in etcd, must be encrypted at rest), and external-secrets-operator that syncs from a secrets manager into Kubernetes at runtime.
Principle of Least Privilege for Secrets
Each application or service should access only the secrets it specifically requires — the principle of least privilege applied to secrets. A web application needs the database password but not the CA private key. A reporting job needs read-only database credentials, not write access. Secrets managers enforce this through access policies that specify which identities (IAM roles, service accounts, AppRoles) can read which secrets, with all access logged for audit purposes.
# Vault policy: web application can read DB password only
# policy name: web-app-policy
# path 'secret/prod/database' {
# capabilities = ['read']
# }
# path 'secret/prod/tls-certs/*' {
# capabilities = [] # DENY - app does not need TLS keys
# }
# This policy is assigned to the web app's AppRole.
# The reporting service gets a separate policy with
# only 'secret/prod/reporting-db-readonly' access.Dynamic Secrets
Dynamic secrets are generated on-demand for a specific requestor and expire automatically. Vault can generate a temporary database credential that is valid for 1 hour, associated with the specific service that requested it. After expiration, the credential is automatically revoked by the database. This approach means there are no long-lived static credentials to steal — even if an attacker captures a dynamic credential, it expires quickly and is tied to the requesting identity in audit logs.
# Vault dynamic secrets: temporary DB credentials
# Application calls Vault to get a DB credential:
# vault read database/creds/web-app-role
#
# Vault response:
# username: v-web-app-x7k2m-1234567890 (unique, temporary)
# password: A1b2C3d4E5f6G7h8 (randomly generated)
# lease_duration: 1h (auto-expires)
#
# After 1 hour, Vault instructs DB to revoke this user.
# No static password ever exists for the attacker to steal.Secrets in CI/CD Pipelines
CI/CD pipelines frequently require secrets — cloud provider credentials for deployment, Docker registry tokens, signing keys. Never store secrets in pipeline scripts or configuration files. Instead, use the pipeline platform's built-in secret store (GitHub Actions Secrets, GitLab CI Variables, Jenkins Credentials Store) or fetch secrets from a central vault at runtime using a machine identity. Mark secret variables as masked in logs to prevent accidental exposure in build output.
# GitHub Actions: using secrets in pipeline
# secrets.yml in GitHub Settings -> Secrets (encrypted storage)
# Secret: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
# In .github/workflows/deploy.yml:
# env:
# AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
# AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# Best practice: use OIDC federation instead
# GitHub -> AWS trust relationship via OIDC token
# -> No static AWS keys needed at allAuditing Secret Access
Secrets managers provide comprehensive audit logs of every secret access event: which identity accessed which secret, from which IP, at what time, and whether the access was successful or denied. These logs are critical for compliance (SOC 2, PCI-DSS) and incident response. When a credential is suspected of compromise, audit logs reveal which systems accessed it and when — enabling rapid identification of potentially affected systems and containment decisions.
Pre-Commit Hooks for Secret Prevention
Pre-commit hooks are scripts that run automatically before each git commit is finalized, enabling detection of secrets before they enter version control history. Tools like detect-secrets (Yelp), GitLeaks, and git-secrets (AWS) integrate as pre-commit hooks and scan staged files for patterns matching API keys, connection strings, private keys, and JWT tokens. If a secret is detected, the commit is rejected and the developer is prompted to remove the credential. The pre-commit framework makes it easy to add and share hook configurations across teams.
# Installing detect-secrets as pre-commit hook:
# 1. Install: pip install detect-secrets
# 2. Create baseline: detect-secrets scan > .secrets.baseline
# 3. Add to .pre-commit-config.yaml:
# repos:
# - repo: https://github.com/Yelp/detect-secrets
# rev: v1.4.0
# hooks:
# - id: detect-secrets
# args: ['--baseline', '.secrets.baseline']
# 4. Install hooks: pre-commit install
# Now every commit attempt is scanned:
# git commit -m 'add config'
# -> detect-secrets runs
# -> if AWS key pattern found: COMMIT BLOCKED
# -> developer must remove secret and use secrets managerQuick Check
Test your understanding of CompTIA Security+ (SY0-701) concepts from this lesson.
Lesson Recap
In this lesson you learned: hardcoded secrets in source code must be eliminated and replaced with secrets managers like Vault or AWS Secrets Manager, automatic rotation removes long-lived credentials that attackers could abuse even after initial compromise, and dynamic secrets and least-privilege access policies minimize the value of any individual secret that is exposed. Next up we explore dependency security and software composition analysis.
Frequently asked questions
Is the “Secure Secret Management and Environment Variables” lesson free?
Yes — the full text of “Secure Secret Management and Environment Variables” is free to read here on the web, and the Cloud & IT Cert Prep course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Cloud & IT Cert Prep course, upgrade to CoddyKit PRO.
What will I learn in “Secure Secret Management and Environment Variables”?
Avoid hardcoded secrets in source code by using secrets managers (Vault, AWS Secrets Manager) and environment variable injection at runtime. You practise Cloud & IT Cert Prep with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Cloud & IT Cert Prep?
No prior experience is required. Cloud & IT Cert Prep on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Secure Secret Management and Environment Variables” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Cloud & IT Cert Prep lesson?
Yes. Every Cloud & IT Cert Prep lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Input Validation and Output Encoding
- Secure Secret Management and Environment Variables
- Dependency Security and Software Composition Analysis
- DevSecOps: Shifting Security Left into Pipelines