Your development pipeline is a privileged system. It has access to source code, deployment credentials, cloud provider keys, and production infrastructure. If an attacker compromises your CI/CD pipeline, they don’t need to find a vulnerability in your application — they can inject one directly, sign it with your certificate, and deploy it to your production environment through your own automation. The SolarWinds attack wasn’t a software vulnerability. It was a pipeline compromise. And most pipelines are far less secured than SolarWinds’ was.

This guide covers the specific, actionable steps to secure your development workflow — from branch protection to deployment. Every item is something you can implement this week. Most are free.

DO / DON’T

DO:

DON’T:

Branch Protection

Branch protection is the first line of defense. Without it, any developer (or any compromised developer account) can push directly to main and trigger a production deployment.

What to Enable

GitHub’s branch protection documentation covers the configuration. GitLab uses “protected branches” with similar options. Enable everything. Loosen later only with documented justification.

Code Review with Security Focus

Code reviews catch what automated tools miss: business logic flaws, authorization bypasses, insecure design patterns, and assumptions about trust boundaries.

Security Review Checklist

Every reviewer should ask:

Automate what you can. Enforce the rest through reviewer training and review checklists. The OWASP Code Review Guide provides detailed guidance by vulnerability class.

SAST in Your Pipeline

Static Application Security Testing scans source code for vulnerability patterns. Add it to every pull request so findings appear before code merges.

Quick Setup

Semgrep (free, open-source, fast):

# GitHub Actions example
- name: Semgrep
  uses: returntocorp/semgrep-action@v1
  with:
    config: "p/default p/owasp-top-ten p/security-audit"

CodeQL (free for public repos, GitHub-native):

# GitHub Actions — enable in repository Settings > Code security
- name: CodeQL Analysis
  uses: github/codeql-action/analyze@v3

Configure findings to appear as PR annotations — inline comments on the specific lines with the issue. Developers fix what they see in their workflow. They ignore what lives in a separate dashboard.

Start by blocking on critical and high findings. Warn on medium. Revisit the thresholds monthly as false positives are tuned out.

Dependency Scanning

Your application is mostly other people’s code. Scan it.

Automated Dependency Updates

Manual Audits

Run these regularly and in CI:

# Node.js
npm audit

# Python
pip audit

# Ruby
bundle audit

# Go
govulncheck ./...

# Rust
cargo audit

Block deployments when critical vulnerabilities with known exploits are found. Check against the CISA KEV catalog — if your dependency is on that list, it’s being actively exploited right now.

Secrets Management

Secrets in code are the most preventable and most common pipeline security failure.

Prevention

Pre-commit hooks catch secrets before they enter the repository:

# Install gitleaks as a pre-commit hook
brew install gitleaks  # or download from GitHub releases
gitleaks protect --staged

CI scanning catches what hooks miss (developers can skip hooks):

# GitHub Actions
- name: Gitleaks
  uses: gitleaks/gitleaks-action@v2

Remediation

If a secret reaches the repository, rotating it is more important than removing it from history. Git history is distributed — the secret is already on every developer’s machine, in every fork, and potentially in cached copies. Rotate the secret immediately, then clean the history with git filter-repo or BFG Repo-Cleaner.

Proper Secret Storage

Use a vault. Not environment variables. Not config files. A vault.

Every secret should have an owner, an expiration, and a rotation schedule. NIST SP 800-57 provides key management lifecycle guidance.

CI/CD Infrastructure Hardening

Your CI/CD system is a production system. Treat it like one.

If It Already Happened

If secrets have been leaked in your repository, rotate them immediately — before cleaning the git history. The secret is compromised the moment it’s pushed, regardless of how quickly you remove it.

If your pipeline has been compromised, treat it as a full security incident. Audit every deployment made by the compromised pipeline. Check for unauthorized code changes, unexpected dependency additions, and modified build scripts. Review CI/CD logs for unusual activity. Rotate all secrets that the pipeline had access to. Rebuild your pipeline infrastructure from known-good configurations.

If malicious code was deployed to production through the pipeline, initiate your incident response process. Identify the affected systems and data. Notify stakeholders per your incident response plan. CISA accepts voluntary incident reports and can provide assistance.


Your pipeline deploys your code, with your credentials, to your production environment. Every control in this guide protects that chain of trust. Start with branch protection and a SAST scanner in CI. Add dependency scanning and secrets detection. Harden the CI/CD infrastructure. Each step closes an attack vector that the usual suspects are actively exploiting. The pipeline is the path to production — lock it down.