Building Security Into CI/CD Pipelines
Building Security Into CI/CD Pipelines
Shift-left security integrates controls throughout the development pipeline rather than treating security as a gate before production. This approach identifies and fixes vulnerabilities when they're cheapest to address while maintaining development velocity. Effective pipeline security requires automation, clear feedback, and developer-friendly tooling.
Source code analysis identifies security issues before container builds. SAST (Static Application Security Testing) tools detect common vulnerabilities in application code. Dependency scanning identifies vulnerable libraries requiring updates. Secret scanning prevents credential exposure. These checks run automatically on every commit, providing immediate feedback to developers.
# GitLab CI/CD pipeline with comprehensive security
stages:
- build
- test
- security
- deploy
- verify
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
IMAGE_TAG: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
# SAST scanning
sast:
stage: security
script:
- /analyzer run
artifacts:
reports:
sast: gl-sast-report.json
only:
- branches
- merge_requests
# Dependency scanning
dependency_scanning:
stage: security
image: registry.gitlab.com/gitlab-org/security-products/dependency-scanning:latest
script:
- /analyzer run
artifacts:
reports:
dependency_scanning: gl-dependency-scanning-report.json
# Container scanning
container_scanning:
stage: security
image: registry.gitlab.com/gitlab-org/security-products/analyzers/klar:latest
variables:
CLAIR_DB_IMAGE_TAG: "latest"
DOCKERFILE_PATH: "Dockerfile"
script:
- /analyzer run
artifacts:
reports:
container_scanning: gl-container-scanning-report.json
# License compliance
license_scanning:
stage: security
image: registry.gitlab.com/gitlab-org/security-products/license-finder:latest
script:
- /analyzer run
artifacts:
reports:
license_scanning: gl-license-scanning-report.json
# Secret detection
secret_detection:
stage: security
image: registry.gitlab.com/gitlab-org/security-products/secret-detection:latest
script:
- /analyzer run
artifacts:
reports:
secret_detection: gl-secret-detection-report.json
# Kubernetes manifest validation
validate_manifests:
stage: security
image: garethr/kubeval:latest
script:
- kubeval manifests/*.yaml
# Policy validation with OPA
policy_check:
stage: security
image: openpolicyagent/opa:latest
script:
- opa test policies/
- opa eval -d policies/ -i manifests/deployment.yaml "data.kubernetes.admission.deny[x]"
# Security gate
security_gate:
stage: security
image: alpine:latest
script:
- apk add --no-cache jq curl
- |
CRITICAL_VULNS=$(cat gl-container-scanning-report.json | jq '[.vulnerabilities[] | select(.severity=="Critical")] | length')
if [ $CRITICAL_VULNS -gt 0 ]; then
echo "Critical vulnerabilities found. Blocking deployment."
exit 1
fi
dependencies:
- container_scanning
only:
- master
- production
# Signed image push
push_signed_image:
stage: deploy
image: gcr.io/projectsigstore/cosign:latest
script:
- cosign sign --key $COSIGN_KEY $IMAGE_TAG
- cosign verify --key $COSIGN_PUB_KEY $IMAGE_TAG
only:
- master
- production
Feedback mechanisms must provide actionable information without overwhelming developers. Security findings should include clear descriptions, severity ratings, and remediation guidance. Integration with development tools like IDEs and pull request systems brings security information into developer workflows. Gamification through security scorecards motivates teams to improve their security posture.