CI/CD Security Checklist

Assess CI/CD pipeline security across secrets management, SAST/DAST, artifact signing, SLSA framework, and deployment controls.

Advertisement

CI/CD security checklist: 30 pipeline controls, scored as you mark them

Work through 30 controls across six areas of a build and deploy pipeline, marking each one pass or fail. The tool keeps a running score, counts how many failures are critical, tracks how many of the supply-chain controls you are meeting, and exports a plain-text report that includes remediation guidance for everything you marked as failing. It runs entirely in your browser — nothing about your pipeline is transmitted or stored anywhere.

This is a self-assessment, not an audit, and passing every item certifies nothing. What it gives you is a concrete list to walk your pipeline against, with each item written specifically enough to check in an afternoon rather than argue about.

The six categories

CategoryItemsWhat it covers
Secrets Management5Hardcoded secrets, log masking, OIDC for cloud auth, scope and rotation, access auditing
Code Security (SAST/SCA)5Static analysis on every PR, dependency scanning, licence compliance, blocking gates, false-positive triage
Build Security5Reproducible builds, ephemeral environments, SHA-pinned actions, provenance, network isolation
Artifact Security5Signing, image scanning, SBOM generation, registry access control, retention
Deployment Security5Production approvals, deployment audit logs, tested rollback, IaC review, scoped deploy credentials
Access Controls5SSO and MFA, least-privilege workflow permissions, branch protection, third-party app review, fork PR restrictions

Each item carries a severity badge — the 30 break down as 4 critical, 16 high, 8 medium and 2 low — a one-line explanation of why it matters, and remediation text naming concrete tools and settings. The remediation text only appears once you mark an item as failing, which keeps the list readable while you are working through it.

The four critical items

Four controls are marked critical, and marking any of them as failing raises a banner counting the critical issues found. They are the ones where a single failure hands an attacker the pipeline rather than merely weakening it.

  • No hardcoded secrets in code or config files. Private repositories are not a control — forks, clones, backups, contractor access and repo history all outlive the decision to keep it private. The remediation names secret managers and CI/CD secret variables for storage, and gitleaks or git-secrets for finding what is already committed. Rotate anything you find; deleting the line does not un-leak it.
  • Dependency scanning (SCA) is enabled. Vulnerable third-party libraries are the most common way a vulnerability arrives in code nobody wrote. Dependabot, Snyk and Trivy are named, with automatic PRs for security updates.
  • Actions and plugins are pinned to a commit SHA. Referencing a mutable tag such as @v4 means whoever controls that tag controls code running inside your build with access to its secrets. Pinning to a full SHA and letting Dependabot bump the pins is the fix.
  • The CI/CD platform has SSO and MFA enabled. Everything else on this list assumes the pipeline's own control plane is not trivially accessible with a stolen password.

How the score is calculated

The headline security score is simply the number of items you marked pass, divided by 30, rounded to a whole percentage. There are two consequences worth knowing before you read your number.

First, severity does not weight the score. Passing the two low-severity items counts exactly as much as passing the four critical ones. The critical count is surfaced separately, in a banner, precisely because the percentage will not tell you about it — a 90% score with one failed critical item is a worse position than a 75% score with none. Read the banner first.

Second, unchecked items count against you. The denominator is always 30, so anything you have not marked is arithmetically identical to a failure while you are part-way through. Expect the score to climb steadily as you fill the list in; it is only meaningful once every item has a state. The colour bands are 80% and above in green, 60% to 79% in yellow, below 60% in red.

A worked example: mark 24 items pass, 4 fail and 2 unchecked and the score reads 80% — 24 divided by 30 — with a Failed count of 4 and an Unchecked count of 2 shown alongside. The three counters always add up to 30, which is the quickest way to see whether you have finished.

The SLSA alignment figure

Ten of the 30 items are tagged with a SLSA level badge, and a separate panel shows what percentage of those ten you are passing. The tagging breaks down as:

SLSA tagItemsControls
L13SAST on every PR, dependency scanning, SBOM generated for releases
L25OIDC for cloud auth, reproducible builds, ephemeral build environments, SHA-pinned actions, signed artifacts
L32Build provenance generated, build isolation preventing network access

Be precise about what this number is. It is the proportion of those ten tagged items you have marked pass — pass seven of the ten and it reads 70%. It is not a SLSA level, and reaching 100% here does not mean you have attained any SLSA level, which is determined against the framework's own requirements and, at the higher levels, verified provenance rather than a self-marked checkbox. Treat the figure as a rough indicator of how much supply-chain hardening you have in place relative to the ten items this list happens to cover.

The controls people most often get wrong

A few items are worth expanding, because they are the ones teams routinely believe they pass when they do not.

Secrets masked in CI/CD logs. Platform masking catches the literal secret value. It does not catch a secret that has been transformed — base64-encoded, embedded in a URL, JSON-escaped, or printed as part of a larger blob. If a job constructs a value from a secret, mask the derived value explicitly (in GitHub Actions, echo "::add-mask::$VALUE") rather than assuming the platform infers it.

Fork PRs have limited permissions. The distinction the remediation points at is between pull_request and pull_request_target. The latter runs the workflow definition from the base branch but can be induced to check out and execute code from the fork, with access to repository secrets — which is why it appears in real supply-chain incidents. If you use it, do not check out untrusted code in the same job as the secrets.

Workflow permissions follow least privilege. The default token permissions on many platforms are broader than any individual job needs. Setting an empty permission block at workflow level and granting only what each job requires turns a compromised step into a much smaller problem.

Builds are reproducible. This is a stronger claim than "we have a lock file". It means the same source produces a byte-identical artifact: pinned dependency versions, no embedded build timestamps, no ambient state from the runner. Most pipelines that mark this pass are actually passing "we pin our dependencies", which is a genuine improvement but a different control.

Build isolation prevents network access. The hardest item on the list for most teams, because package installation itself needs the network. A hermetic build resolves dependencies in a separate, verified step, then runs the compile with egress blocked. Marking this fail is a normal answer.

Exporting your results

Two output actions sit above the list. Copy puts a single summary line on your clipboard — score, passed out of total, and failed count — which is what you want for a status update or a ticket comment. Export downloads cicd-security-checklist.txt containing a timestamp, the overall score, the pass and fail counts including the critical count, the SLSA alignment percentage, and then every category with each item marked [PASS], [FAIL] or [ ]. Failed items get their full remediation text written underneath them, which makes the export usable directly as a work list.

The export is the only durable record. There is no autosave, no account and no stored state: reloading the page clears every mark. For a 30-item list that takes a while to work through with other people, export before you close the tab, and re-import by re-marking — the tool cannot read a report back in.

Practical notes on running it

  • Each item has only pass and fail buttons. There is no not-applicable control in the interface, so a genuinely inapplicable item — container scanning when you ship no containers — has to be marked fail or left blank, and either choice depresses the score. Note those cases separately when you report the number.
  • Clicking the same button again does not clear it; use Reset to start over, which clears every mark at once.
  • Categories collapse and expand by clicking their header, and each header shows a passed-out-of-total count so you can see progress per area with everything collapsed.
  • Run it per pipeline, not per organisation. A mature production deployment pipeline and a two-year-old internal tool's workflow will score very differently, and averaging them hides the one that matters.
  • Re-run after any significant change to the pipeline, and after adding a new third-party action — the pinning and third-party review items go stale fastest.

If your pipeline invokes AI tooling that connects to external Model Context Protocol servers, those connections have their own failure modes; the MCP server security checklist covers them separately.

Frequently Asked Questions

What is the SLSA framework?+

SLSA (Supply-chain Levels for Software Artifacts) is a security framework for protecting software supply chains. It defines four levels of increasing security guarantees, from basic build provenance (L1) to hermetic, reproducible builds (L4).

How do I secure secrets in CI/CD pipelines?+

Never hardcode secrets in code or config files. Use your CI/CD platform's secret management (GitHub Secrets, GitLab CI Variables). Better yet, use OIDC for cloud authentication to eliminate stored credentials.

What is the difference between SAST and DAST?+

SAST (Static Application Security Testing) analyzes source code without running it. DAST (Dynamic Application Security Testing) tests running applications. Use both for comprehensive coverage.

Why should I pin GitHub Actions to SHA?+

Pinning actions to commit SHAs prevents supply chain attacks. Tags can be moved to point to malicious code, but SHAs are immutable. Use actions/checkout@b4ffde65f46... instead of @v4.

What is build provenance and why does it matter?+

Build provenance is cryptographic evidence of where an artifact came from. It enables verification that artifacts weren't tampered with. Generate provenance using SLSA GitHub generator or sigstore/cosign.

How do I implement least privilege in CI/CD?+

Set permissions: {} at the workflow level to disable all permissions, then grant only what's needed per job. Use environment-specific credentials and avoid admin tokens in pipelines.

This tool is provided for informational and educational purposes only. All processing happens in your browser — no data is sent to or stored on our servers. While we strive for accuracy, we make no warranties about the completeness or reliability of results.