Securing Database Connection Strings
Best practices for securing database connection strings. Covers environment variables, secret managers, credential rotation, and common security mistakes.
Detailed Explanation
Security Best Practices
Database connection strings contain sensitive credentials. Mishandling them can expose your entire database to unauthorized access.
Rule 1: Never Hardcode Credentials
Bad:
// DO NOT do this
const db = new Pool({
connectionString: 'postgresql://admin:SuperSecret123@db.example.com/prod'
});
Good:
const db = new Pool({
connectionString: process.env.DATABASE_URL
});
Rule 2: Use Environment Variables
Store connection strings in environment variables. Common approaches:
.env file (local development only):
DATABASE_URL="postgresql://user:pass@localhost:5432/dev"
Never commit .env files. Add to .gitignore:
.env
.env.local
.env.production
Rule 3: Use Secret Managers in Production
For production, use dedicated secret management:
- AWS Secrets Manager / AWS SSM Parameter Store
- Google Cloud Secret Manager
- Azure Key Vault
- HashiCorp Vault
- Doppler, Infisical, or similar SaaS
These provide audit logging, automatic rotation, and access control that environment variables alone cannot offer.
Rule 4: Principle of Least Privilege
Create database users with minimal required permissions:
-- PostgreSQL: read-only user for reporting
CREATE USER reporter WITH PASSWORD 'readonly_pass';
GRANT CONNECT ON DATABASE myapp TO reporter;
GRANT USAGE ON SCHEMA public TO reporter;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO reporter;
Use separate credentials for different services. Never use the superuser (postgres, root, sa) for application connections.
Rule 5: Rotate Credentials
Regularly rotate database passwords. With a secret manager, this can be automated:
- Generate new password
- Update database user
- Update secret in secret manager
- Application picks up new credentials on next connection pool refresh
Common Mistakes
| Mistake | Risk | Fix |
|---|---|---|
Committing .env to git |
Credential exposure | .gitignore |
| Logging connection strings | Credentials in log files | Mask passwords in logs |
| Using root/admin in production | Full DB access if compromised | Dedicated app users |
| Same credentials for dev/prod | Dev compromise = prod breach | Separate credentials |
| No SSL in production | Credentials sent in plaintext | Always use SSL |
Use Case
Implementing a secure credential management strategy for a production application, preparing for a security audit, or setting up a CI/CD pipeline that injects database credentials safely.