Securing Your Deployments: A Practical Guide

January 15, 2025
security devops ci-cd best-practices

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:

  1. Separate environments: Dev, staging, and production should have different access levels
  2. Role-based access: Use IAM roles instead of long-lived credentials
  3. 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.