Securing Your Deployments: A Practical Guide
Security in the Deployment Pipeline
Security isn’t just a production concern—it needs to be baked into every stage of your deployment pipeline. In this guide, we’ll cover practical steps to secure your CI/CD workflows.
1. Secrets Management
Never commit secrets to your repository. This seems obvious, but it’s still one of the most common security mistakes.
What to Do Instead
Use a proper secrets management system:
// Bad: Hardcoded credentials
const apiKey = "sk_live_abc123def456";
// Good: Load from environment
const apiKey = process.env.API_KEY;
Store secrets in:
- AWS Secrets Manager
- HashiCorp Vault
- GitHub Secrets
- Cloud provider key management services
Secret Scanning
Enable automated secret scanning in your repository. Tools like:
- git-secrets: Prevents committing secrets
- TruffleHog: Scans for secrets in git history
- GitHub Secret Scanning: Automatic detection and alerts
2. Dependency Scanning
Third-party dependencies are a major attack vector. Regularly scan for vulnerabilities:
# For Node.js projects
npm audit
# For Python projects
pip-audit
# For comprehensive scanning
snyk test
Automated Scanning in CI/CD
Add dependency checks to your pipeline:
steps:
- name: Install dependencies
run: npm install
- name: Security audit
run: npm audit --audit-level=high
3. Container Security
If you’re using Docker, follow these practices:
Use Minimal Base Images
# Instead of
FROM node:latest
# Use specific, minimal images
FROM node:20-alpine
Scan Images for Vulnerabilities
# Using Trivy
trivy image myapp:latest
# Using Docker Scout
docker scout cves myapp:latest
Run as Non-Root User
FROM node:20-alpine
# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs
4. Access Control
Implement principle of least privilege:
- Separate environments: Dev, staging, and production should have different access levels
- Role-based access: Use IAM roles instead of long-lived credentials
- Approval workflows: Require manual approval for production deployments
Example: Approval Requirements
environments:
production:
requires_approval: true
approvers:
- security-team
- tech-lead
5. Audit Logging
Log everything that happens in your pipeline:
- Who triggered the deployment
- What code was deployed
- When it was deployed
- Any approvals or overrides
This creates an audit trail for compliance and incident investigation.
6. Network Security
Protect your deployment infrastructure:
- Use private networks for build agents
- Restrict outbound connections
- Enable VPC endpoints for cloud services
- Use TLS for all communications
Common Pitfalls to Avoid
❌ Don’t: Print secrets in logs
console.log("Connecting with password:", password); // BAD!
❌ Don’t: Use wildcard permissions
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
❌ Don’t: Skip security scans to “move faster”
Security issues compound over time. Fix them early.
Checklist for Secure Deployments
- [ ] Secrets stored in secure vault
- [ ] Secret scanning enabled
- [ ] Dependency scanning in CI/CD
- [ ] Container images scanned
- [ ] Running as non-root user
- [ ] Approval required for production
- [ ] Audit logging enabled
- [ ] Network access restricted
- [ ] TLS enabled everywhere
- [ ] Regular security updates
Conclusion
Security doesn’t have to slow you down. By automating security checks in your pipeline, you can move quickly while maintaining a strong security posture.
The key is to make security checks automatic and non-negotiable. When security is part of the pipeline, it happens every time—no exceptions.
For more security best practices, check out our guide on Infrastructure as Code Security.