Zero Data RetentionQuantum-Ready Entropy256-bit MinimumClient-Side OnlyPost-Quantum ReadyZero KnowledgeNIST SP 800-63BFIPS 140-3 AlignedNo Account NeededDoD CompliantZero Data RetentionQuantum-Ready Entropy256-bit MinimumClient-Side OnlyPost-Quantum ReadyZero KnowledgeNIST SP 800-63BFIPS 140-3 AlignedNo Account NeededDoD Compliant
Developers15 min readUpdated March 2025

Password Security for Developers: Secrets, Credentials, and APIs

Developers manage more credentials than anyone. This guide covers personal account security, API key hygiene, secrets management, and hardcoded credential risks.

Your credential attack surface

A software developer's credential attack surface is vastly larger than a typical employee's. In a given week, a developer might authenticate to: GitHub/GitLab, AWS/GCP/Azure console, production and staging databases, Vercel/Netlify/Railway, Stripe, PagerDuty, Datadog, Sentry, internal admin panels, SSH servers, Kubernetes clusters, HashiCorp Vault, and a dozen SaaS tools. Each is an attack vector. Each credential, if compromised, can cascade.

Developer credentials are also disproportionately high-value targets. A compromised GitHub account with production deploy access is worth vastly more to an attacker than a standard employee's email account. Supply chain attacks — injecting malicious code via compromised developer credentials — have caused some of the most damaging breaches of the past five years (SolarWinds, Codecov, CircleCI).

Personal account hygiene

Start with the fundamentals before addressing the developer-specific risks:

  • GitHub/GitLab: Enable MFA (prefer hardware key or TOTP, not SMS). Use SSH keys for repository access rather than HTTPS with password. Enable commit signing with GPG.
  • Cloud consoles: MFA on every cloud account without exception. Root/owner accounts should use hardware MFA (YubiKey). Enable login notifications.
  • Email: Your developer email account is a recovery target for every other account. It needs the strongest MFA you have — hardware key if possible. If it falls, everything falls.
  • Package registry accounts: npm, PyPI, RubyGems — these accounts can be used to push malicious packages. Enable MFA. Review what you've published and whether it's still maintained.
Hardware key for developers: A YubiKey 5 supports FIDO2/WebAuthn (for GitHub, cloud consoles), TOTP (for any TOTP site), OpenPGP (for commit signing and email encryption), and PIV (for smart card use). One device covers nearly every authentication use case a developer faces. Buy two — one for daily use, one as a backup stored off-site.

Secrets management fundamentals

The core principle: secrets should never be stored in the same place as code. The mechanisms for achieving this have matured significantly:

  • Development: Use .env files (never committed) or local secrets manager tooling (1Password CLI, Doppler, direnv)
  • CI/CD: Use your platform's native secrets store (GitHub Actions Secrets, GitLab CI Variables, CircleCI Contexts) — never hardcode in workflow files
  • Production: Use a dedicated secrets management service: HashiCorp Vault (self-hosted), AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, Doppler, or Infisical
  • Rotation: All production secrets should be rotatable with zero downtime. If rotating a secret requires a deploy, the architecture has a problem.

The secret management hierarchy in a well-run system:

  1. Vault / cloud secrets manager holds the canonical secret
  2. Applications authenticate to the vault using short-lived tokens (IAM roles, Vault dynamic credentials)
  3. Secrets are injected at runtime, never written to disk or included in container images
  4. Access to the vault itself is logged, audited, and protected with hardware MFA

.env files and what goes wrong

The .env file pattern is ubiquitous in development. It works well when used correctly and catastrophically when not. The rules:

  • Always add .env to .gitignore before the first commit. Adding it later doesn't remove existing history — you need to use git filter-branch or git filter-repo, and the credentials may already be on remotes or forks.
  • Commit a .env.example with dummy values but never commit a .env with real values, even in a private repository.
  • Private repositories are not secret storage. GitHub employees, GitHub security scanning, future collaborators, and anyone who gets read access to the repo all see the full Git history. A secret in a private repo's history is a secret that has been shared with GitHub infrastructure.
  • Different secrets per environment. Development, staging, and production should have different credentials. A developer's local .env should never contain production database credentials.

Credentials in Git — the biggest risk

Accidentally committing credentials to a Git repository is the most common developer security incident. GitHub's secret scanning service finds and reports known credential patterns automatically, but by the time a notification arrives, the secret may already have been indexed by public scanners.

If you commit a secret to a public repository:

  1. Revoke the secret immediately — before fixing the code, before telling anyone. The secret is already compromised.
  2. Check your cloud provider's access logs for the period since the commit to identify any unauthorised use
  3. Rotate the secret to a new value
  4. Remove the secret from Git history using git filter-repo (the modern replacement for filter-branch)
  5. Force-push to overwrite the history on all remotes
  6. Notify any forks or collaborators who may have cloned the repository during the exposure window

Tools that help prevent this: git-secrets (AWS), detect-secrets (Yelp), gitleaks, and truffleHog — run as pre-commit hooks to catch credentials before they reach a remote.

API key hygiene

Most developer credential incidents involve API keys rather than passwords. Best practices:

  • Scope minimally: Create API keys with the minimum permissions required. A key for reading analytics data should not have write access to production data.
  • One key per environment: Separate keys for development, staging, and production. If a dev key leaks, production is not exposed.
  • Set expiry: Most platforms support API key expiry. Use it. Short-lived keys reduce the exposure window if a key is compromised.
  • Rotate regularly: API keys for production systems should be rotated on a schedule — quarterly at minimum, or on any suspected exposure.
  • Audit active keys: Review which API keys are active, which are being used, and which haven't been called in 90+ days. Inactive keys are attack surface with no benefit — revoke them.
  • Never log API keys: Application logs frequently capture request headers and body contents. Ensure your logging configuration redacts authorization headers.

SSH key management

  • Use Ed25519, not RSA-2048: ssh-keygen -t ed25519 -C "your_email@example.com". Ed25519 is faster, shorter, and considered more secure than RSA-2048 or RSA-4096.
  • Passphrase-protect your private key: Use a strong random passphrase (generated by PassGeni or your password manager). The passphrase encrypts the private key on disk — if someone gets your key file, they can't use it without the passphrase.
  • Use SSH agent: ssh-agent caches your decrypted key in memory so you don't retype the passphrase on every connection. On macOS, 1Password integrates directly as an SSH agent.
  • One key per device: Don't copy your private key across machines. Generate a new key on each device and add its public key to each service. This way, if a device is compromised or lost, you revoke only that device's key.
  • Audit and remove stale keys: Review your GitHub, Bitbucket, and server authorized_keys files periodically. Remove keys from devices you no longer own.

CI/CD pipeline secrets

CI/CD pipelines are high-value targets — they have deployment access and often run with elevated permissions. Common mistakes:

  • Secrets printed in build logs (especially from debug commands or error messages)
  • Secrets in Docker image layers — inspect with docker history to verify no secrets are baked in
  • Shared secrets across all branches — use environment-scoped secrets so feature branches can't access production credentials
  • Overly permissive pipeline service accounts — apply least privilege to the IAM roles your CI/CD assumes

Use short-lived credentials for deployments where possible. OIDC integration between GitHub Actions and AWS/GCP/Azure allows pipelines to authenticate without storing long-lived credentials at all.

Database credentials

Database credentials deserve specific attention because a compromise typically means direct access to all application data:

  • Never connect to production databases from local development machines with production credentials
  • Use different database users per application/service — don't share a single database superuser credential across all applications
  • Database passwords should be at minimum 20 characters, randomly generated, and stored in a secrets manager
  • Enable connection string encryption — use SSL/TLS for all database connections, even inside a VPC
  • Consider dynamic credentials: HashiCorp Vault database secrets engine generates short-lived credentials on-demand, eliminating long-lived database passwords entirely

Team credential sharing

The inevitable reality of small dev teams: some credentials need to be shared (staging database, shared API keys, deployment accounts). The wrong way: Slack DMs, email, shared Google Docs. The right way:

  • 1Password Teams: Shared vaults, granular permissions, audit logs, and automatic access revocation when someone leaves the team. The standard tool for dev team credential management.
  • Bitwarden Teams: Open-source option with shared organisations. Slightly less polished UX but free for small teams and fully self-hostable if you need on-premises storage.
  • For production secrets specifically: Use a dedicated secrets manager (Vault, Doppler, Infisical) — not a password manager. Applications should fetch secrets dynamically, not a developer looking them up and pasting them.
Team password manager for developers: 1Password Teams ($4/user/month) is the standard for development teams — shared vaults, CLI integration (op run for injecting secrets into processes), SSH agent integration, and automatic access revocation. Bitwarden Teams is the open-source alternative at lower cost.

Password manager setup for developers

The recommended setup for a developer's personal credential management:

  1. Choose a password manager: 1Password (best UX, SSH agent integration) or Bitwarden (open-source, self-hostable)
  2. Set a strong, unique master password — a 6-word Diceware passphrase you have memorised and stored nowhere digitally
  3. Enable MFA on your password manager account — hardware key as first factor if supported
  4. Migrate all existing credentials into the vault — use the built-in audit tools to identify duplicates, weak passwords, and breached credentials
  5. Install the browser extension and desktop app — auto-fill removes the friction of strong unique passwords
  6. Set up the CLI: 1Password CLI (op) or Bitwarden CLI (bw) allows secrets injection into local development scripts and terminal workflows
  7. Configure SSH agent integration if available — 1Password can serve as your SSH agent, so your key passphrase is protected by your vault's biometric unlock

Frequently asked questions

What password security practices should developers follow?

Developers should use a password manager for all credentials, generate unique passwords for every service, enable MFA on all accounts (especially GitHub, AWS, and cloud consoles), and never hardcode credentials in code. Service account passwords should be managed via a secrets manager.

How should API keys be stored securely?

API keys should never be hardcoded in source code. Use environment variables locally (.env files, never committed), CI/CD secret variables for automation, and a secrets manager (HashiCorp Vault, AWS Secrets Manager, Doppler) for production. Store only the SHA-256 hash server-side when issuing keys to users.

What password hashing algorithm should I use in 2025?

Argon2id is the current best practice, winning the Password Hashing Competition and recommended by OWASP. bcrypt remains acceptable. Use a work factor (cost factor) of at least 10 for bcrypt, or memory of 64MB and 3 iterations for Argon2id. Never use MD5, SHA-1, or SHA-256 alone without iteration.

How do I prevent credential stuffing against my application?

Enable MFA, check passwords against the HIBP breach database at registration and login, implement rate limiting per IP (not just per account), use anomaly detection to flag distributed authentication failures, and consider passkey support to eliminate passwords from the authentication flow entirely.

What NIST guidelines apply to software authentication?

NIST 800-63B Digital Identity Guidelines covers verifiers (your authentication system). Key requirements: minimum 8 characters (64+ recommended maximum), check against breached credential lists, no complexity requirements (length is the primary control), no mandatory rotation without evidence of compromise, support all printable ASCII and Unicode.

Should I force password changes on a schedule in my app?

No — NIST 800-63B explicitly discourages mandatory periodic rotation. Force password changes only when credentials appear in breach databases (check via HIBP API) or when a user reports compromise. Forced rotation without cause trains users to make minimal predictable changes.

How do I implement secure password reset flows?

Password reset links should be single-use, expire within 15–30 minutes, and be sent to the registered email (which you don't control, so consider this a weak link). The reset link should not contain the user ID in a guessable format. After reset, invalidate all existing sessions. Never send passwords via email.

What is the minimum password length for a production application?

NIST recommends accepting passwords of at least 8 characters minimum, with no upper limit below 64 characters. In practice, set your minimum at 12 characters for general accounts and 16 for administrative accounts. Use PassGeni's Team API to generate compliant credentials programmatically if building onboarding flows.

How do I scan for accidentally committed secrets in git history?

Use TruffleHog (open source, scans git history with entropy analysis) or GitLeaks for local/CI scanning. GitHub Advanced Security provides automatic push protection and secret scanning for repositories. Add pre-commit hooks using detect-secrets to prevent commits containing high-entropy strings.

Can I use PassGeni's API to generate passwords in my application?

Yes — PassGeni's Team API allows programmatic password generation with compliance preset enforcement. The API generates cryptographically random credentials using server-side CSPRNG, returns them over HTTPS, and supports all compliance presets (HIPAA, PCI-DSS, SOC 2, NIST, ISO 27001, DoD). See the API documentation for integration details.

Related guides
← All guidesGenerate password →