DevSecOps
Secrets Management
HashiCorp Vault
DevSecOps
Credential Rotation
+2 more

Secrets Management in DevSecOps: Vault, Rotation & Zero Hardcoded Credentials

SCR Security Research Team
January 31, 2026
20 min read
Share

The Hardcoded Secrets Epidemic

Secrets — API keys, database passwords, tokens, private keys, certificates — are the keys to your kingdom. And they're everywhere they shouldn't be.

GitGuardian 2025 State of Secrets Sprawl: Analyzed 1.5 billion git commits and found 12.8 million new secret occurrences in public repositories in 2024 alone — a 28% increase over 2023. One in every 400 commits contains at least one hardcoded secret.

MetricValueSource
New secrets found in public repos (2024)12.8 millionGitGuardian 2025
Commits containing a secret1 in 400GitGuardian 2025
Avg time a leaked secret stays valid5+ yearsGitGuardian
Orgs with secrets in their codebase73%CyberArk 2025
Breaches involving stolen credentials49%Verizon DBIR 2025
Most common leaked secret typeCloud provider keys (AWS, GCP, Azure)GitGuardian

Types of Secrets and Where They Leak

Secret TypeCommon Leak LocationsImpact if Exposed
AWS Access KeysGit repos, .env files, CI/CD logsFull AWS account access
Database passwordsDocker configs, config filesComplete data breach
API keys (Stripe, SendGrid)Client-side JS, mobile appsFinancial fraud, spam
JWT signing keysSource code, config filesToken forgery, auth bypass
SSH private keysGit repos, shared foldersServer access
TLS private keysDocker images, config reposTraffic interception
OAuth client secretsFrontend code, public reposAccount takeover
Encryption keysEnvironment variables, codeData decryption

Secrets Detection

Pre-Commit Detection (Prevent Leaks)

# Install gitleaks as pre-commit hook
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks

# Alternatively, install gitleaks globally
brew install gitleaks

# Scan entire repository history
gitleaks detect --source . --verbose

# Scan only staged changes (fast, for pre-commit)
gitleaks protect --staged --verbose

CI/CD Detection (Catch What Slipped Through)

# GitHub Actions — Block PRs with secrets
name: Secrets Detection
on: [pull_request]

jobs:
  gitleaks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Secrets Detection Tools Comparison

ToolTypeSpeedCustom RulesBest For
GitleaksPre-commit + CIFastYes (TOML)General-purpose
TruffleHogGit history + liveMediumYesDeep historical scanning
GitGuardianSaaS + CIFastYesEnterprise, remediation tracking
detect-secrets (Yelp)Pre-commitFastYes (plugins)Minimal false positives
SemgrepSAST + secretsMediumYes (YAML)Combined code + secrets scanning

Secrets Management Solutions

HashiCorp Vault

// Node.js — Fetching secrets from HashiCorp Vault
import Vault from "node-vault";

const vault = Vault({
  apiVersion: "v1",
  endpoint: process.env.VAULT_ADDR,
  token: process.env.VAULT_TOKEN, // Use AppRole in production
});

async function getDatabaseCredentials() {
  // Dynamic secret — Vault generates temporary credentials
  const result = await vault.read("database/creds/myapp-readonly");

  return {
    username: result.data.username,    // Temporary username
    password: result.data.password,    // Temporary password
    ttl: result.lease_duration,         // Expires in seconds
    leaseId: result.lease_id,          // For renewal/revocation
  };
}

AWS Secrets Manager

import {
  SecretsManagerClient,
  GetSecretValueCommand,
} from "@aws-sdk/client-secrets-manager";

const client = new SecretsManagerClient({ region: "us-east-1" });

async function getSecret(secretName: string): Promise<Record<string, string>> {
  const command = new GetSecretValueCommand({ SecretId: secretName });
  const response = await client.send(command);

  if (response.SecretString) {
    return JSON.parse(response.SecretString);
  }
  throw new Error("Secret not found");
}

// Usage
const dbConfig = await getSecret("prod/database/credentials");
// dbConfig = { host: "...", username: "...", password: "..." }

Solution Comparison

FeatureHashiCorp VaultAWS Secrets ManagerAzure Key VaultGCP Secret Manager
Dynamic secretsYes (databases, cloud, PKI)NoNoNo
Auto-rotationYesYes (Lambda)YesYes (Cloud Functions)
Transit encryptionYes (built-in)Via KMSVia HSMVia Cloud KMS
Multi-cloudYesAWS onlyAzure onlyGCP only
Open sourceYes (OSS version)NoNoNo
PriceFree (OSS) / Enterprise$0.40/secret/month$0.03/10K operations$0.06/10K operations

Automated Secret Rotation

Why Rotation Matters

  • Limits blast radius — If a secret is leaked, it's only valid until the next rotation
  • Compliance requirement — PCI-DSS, SOC 2, HIPAA all require credential rotation
  • Reduces insider risk — Former employees' knowledge of secrets becomes useless

Rotation Schedules

Secret TypeRotation FrequencyMethod
Database passwords24 hours (dynamic) or 30 daysVault dynamic secrets or AWS rotation Lambda
API keys90 daysAutomated key regeneration
TLS certificates30-90 dayscert-manager / Let's Encrypt auto-renewal
SSH keys90 days or per-sessionVault SSH Secrets Engine
JWT signing keys7 days (with key versioning)Custom rotation with backward compatibility
Cloud access keysNever (use IAM roles instead)Eliminate static cloud keys entirely

CI/CD Secrets Security

RuleImplementation
Never echo secrets in logsset +x in bash; mask in CI config
Use CI-native secret storageGitHub Actions secrets, GitLab CI/CD variables
Rotate CI/CD secrets quarterlyAutomated key rotation workflow
Limit secret scopeRepo-level, not org-level secrets
Audit secret accessReview who/what accessed which secrets
No secrets in Docker build argsUse multi-stage builds + runtime injection
Least-privilege tokensScoped to specific repos/environments

Zero Hardcoded Credentials Maturity Model

LevelDescriptionControls
Level 0: Wild WestSecrets in source code, shared plaintext filesNo controls
Level 1: AwarenessSecrets moved to environment variables.env files, CI secrets
Level 2: ManagedCentralized secrets managementVault/AWS SM, rotation
Level 3: DynamicShort-lived, auto-rotating credentialsDynamic secrets, certificate management
Level 4: Zero StandingNo persistent credentials existJust-in-time access, identity-based auth

Further Reading

Advertisement