Ai/automazione

Secure CI/CD Pipelines: 12-Point Checklist for GitLab & GitHub

Secure CI/CD Pipelines: 12-Point Checklist for GitLab & GitHub

AWS tokens with admin permissions committed in plain text to a public GitHub repository. A CI/CD pipeline with production access that anyone could trigger. This scenario, uncovered during a security audit, is not an exception but a far too common reality. Continuous Integration and Continuous Delivery (CI/CD) pipelines have become the heart of modern software development, accelerating releases and improving quality. However, this automation introduces new attack surfaces, transforming each pipeline into a potential backdoor to the production environment.

Ignoring CI/CD pipeline security means exposing your entire infrastructure to significant risks. A 2024 Snyk report revealed that 68% of organizations experienced at least one software supply chain security incident in the last year. Most of these incidents were attributable to vulnerabilities or misconfigurations in CI/CD pipelines. As IT professionals, our task is not only to implement automation but also to ensure its robustness and resilience against threats. This guide provides a 12-point operational checklist, focusing on GitLab and GitHub Actions, to fortify your pipelines and ensure peace of mind.

Prerequisites / Test Environment

To test and implement these best practices, you will need a development environment with access to:

  • A Git repository (GitHub or GitLab).
  • A configured CI/CD environment (GitHub Actions or GitLab CI/CD).
  • Access to a Secret Manager (e.g., HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, Google Secret Manager) or the native secret management features of your CI/CD platform.
  • Security scanning tools for code and dependencies (e.g., Snyk, Trivy, Gitleaks).
  • Tools for SBOM generation (e.g., Syft) and container image signing (e.g., Cosign).

1-2. Secrets Management: Never in Plain Text, Use Vault or Native Secret Managers

Secret management is arguably the most critical aspect of CI/CD pipeline security. Committing credentials, API keys, or tokens directly into source code, even in .env files or private configurations, is a severe mistake. These secrets can accidentally end up in public repositories or be exposed during a breach.

Action: Use a dedicated Secret Manager. Platforms like HashiCorp Vault offer a centralized and robust solution for secret management. Alternatively, both GitHub Actions and GitLab CI/CD provide native secret management features, which should be your first choice if an external Secret Manager is not available.

Example (GitHub Actions):

Secrets are configured in the repository’s web interface and referenced in the workflow:

name: Deploy Application
on: [push]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to AWS
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        run: |
          aws s3 sync ./build s3://my-secure-bucket

Action: Implement static analysis tools (SAST) that include secret detection. gitleaks is an excellent open-source tool for this purpose. Run a scan regularly on your codebase to ensure no secrets have accidentally made their way into the repository.

# Scan for exposed secrets in code
gitleaks detect --source . --verbose

This command analyzes the current repository for patterns matching known secrets, providing a detailed report.

3-4. Secure and Isolated Runners

Runners are the virtual machines or containers that execute the operations defined in the pipeline. Their security is paramount.

Action: Do not share runners between projects with different sensitivity levels or between development and production environments. For production environments, consider using dedicated self-hosted runners or ephemeral runners that are created and destroyed for each job. This reduces the attack surface and prevents the persistence of malware or compromised artifacts.

Action: Harden runners. Limit network access, disable unnecessary services, keep the operating system and software updated, and use a read-only root filesystem where possible. GitLab offers the ability to configure config.toml for self-hosted runners, allowing granular control over their capabilities and security.

5-6. Dependency Management: Lock Files, Vulnerability Scans, and SBOM

The software supply chain is an increasingly exploited attack vector. Vulnerable dependencies can compromise the entire application.

Action: Use lock files (e.g., package-lock.json, Gemfile.lock, requirements.txt.hash) to pin the exact versions of all dependencies. This ensures reproducible builds and prevents the automatic introduction of new vulnerabilities through uncontrolled updates.

Action: Integrate dependency vulnerability scanners into the pipeline. Tools like Snyk, OWASP Dependency-Check, or Trivy can identify known CVEs in the libraries used. Furthermore, generate a Software Bill of Materials (SBOM) for each build. An SBOM provides a complete inventory of all software components included in your artifact, facilitating vulnerability management and compliance. Read also: Advanced Kubernetes Debugging: Containers in Crash

# SBOM with Syft
syft myimage:latest -o spdx-json > sbom.json

This command creates an SBOM in SPDX format for the specified Docker image, useful for tracking all dependencies.

7-8. Reproducible and Signed Container Images

If your pipeline produces container images, their integrity and authenticity are crucial.

Action: Ensure container image builds are reproducible (deterministic). This means that, given the same Dockerfile and inputs, the same binary image should always be generated. This is fundamental for verification and auditability.

Action: Sign container images with tools like Cosign (part of the Sigstore project). Digital signing ensures that the image has not been tampered with after the build and that it originates from a trusted source. Signature verification should be a mandatory gate before deployment to production.

# Sign image with Cosign
cosign sign --key cosign.key myregistry/myimage:latest

# Verify signature
cosign verify --key cosign.pub myregistry/myimage:latest

These commands demonstrate how to sign and verify the integrity of a container image, an essential step for supply chain security. For more details on Cosign, refer to the official Sigstore documentation: https://docs.sigstore.dev/cosign/overview/

9-10. Least Privilege for Tokens and Accounts

The principle of least privilege is a cornerstone of security and applies critically to CI/CD pipelines.

Action: Configure the tokens and accounts used by the pipeline with the minimum necessary permissions to perform their job. For example, a deployment token should not have permissions to delete an entire S3 bucket or disable EC2 instances. A common mistake is using an administrator-level token for simplicity, but this creates a huge risk if the token is compromised.

Example (GitHub Actions: least privilege):

permissions:
  contents: read
  packages: write
  # Add only the strictly necessary permissions for the specific job

This YAML block defines the minimum permissions for the workflow, limiting the token’s access to repositories and packages.

Action: Rotate secrets and tokens regularly. Even if a least-privilege token is compromised, frequent rotation reduces the exposure window and potential impact.

11-12. Audit Logs and Alerting on Failed Pipelines

Visibility is a key component of security. Knowing what happens in your pipelines, especially in case of failure or suspicious activity, is crucial.

Action: Enable detailed audit logs for all pipeline activities. These logs should capture who did what, when, and with what outcome. Integrate these logs with your SIEM or centralized monitoring system for analysis and correlation.

Action: Configure proactive alerting for critical events. These include:

  • Unexpected pipeline failures (could indicate a tampering attempt or a security issue).
  • Unauthorized access to runners or secrets.
  • Changes to pipeline configurations or workflow files.
  • Detection of critical vulnerabilities by scanners.

Timely alerts can make the difference between a small anomaly and a large-scale security incident. In an enterprise environment with 2,000 endpoints, effective pipeline alerting prevented a malicious code injection attempt into a container image before it reached production, saving hours of rollback and potential data breaches.

Common Errors and Troubleshooting

  • Secrets committed by mistake: Use git filter-repo or bfg-repo-cleaner to remove secrets from Git history, but be aware that secrets might have already been exposed. Immediate rotation is mandatory.
  • Exposed runners: Verify firewall rules and security groups for self-hosted runners. Ensure only necessary ports are open and only to authorized IP addresses.
  • False positives in scanners: Configure baselines and exceptions for vulnerability scanners, but be careful not to ignore actual warnings. Implement a triaging process for each detected vulnerability.

Conclusions with Operational Takeaways

Improving CI/CD pipeline security is not a one-time activity but a continuous process. Each point in this checklist represents an opportunity to strengthen defenses and reduce risk. Automation should not sacrifice security; on the contrary, a well-designed pipeline can integrate robust security controls from the earliest stages of development. Adopting these 12 best practices will enable you to build a more resilient and reliable software delivery process, protecting your infrastructure and data.

Updated: July 2026

Share this article:

Written by

Rosario Giordano

Rosario Giordano is a system administrator and IT consultant specializing in cybersecurity and cloud, with over 20 years of experience managing enterprise Linux infrastructures. His areas of expertise include SSH hardening, Kubernetes platforms, PostgreSQL databases, VMware/ Proxmox virtualization, and compliance with NIS2 and ISO 27001 security frameworks