OWASP lists improper artifact integrity validation as CICD-SEC-9 and insufficient logging and visibility as CICD-SEC-10; neither problem is solved by buying a scanner that only comments on pull requests. A leaked secret, a compromised dependency, and an unsigned deployment are different failures at different boundaries, so they should never be scored as one vague “CI/CD security” feature.
That distinction matters when a procurement team is comparing a CI-native security tier, an application security platform, a repository manager, and an artifact-signing tool as though they were competing substitutes. They are not. GitHub Advanced Security, GitLab’s built-in capabilities, Checkmarx, JFrog Xray, Cosign, and OPA operate at different layers, have different enforcement points, and create different maintenance obligations.
The useful buying question is not “Which CI/CD security tool is best?” It is: which combination of controls can prove and enforce our release requirements on our actual CI platform? A requirements matrix turns that question into a decision you can audit six months later.
Start with boundaries, not a vendor category
Several recent CI/CD security overviews correctly emphasize visibility, integration, dependency risk, and malicious changes in pipelines. But headline counts are not enough to select a control. For example, the Sonatype material in the research notes states that its research identified more than 454,000 new malicious open-source packages in Q1 2026, but the supplied extract does not state the package ecosystems searched or the detection methodology. Treat that as a reason to test dependency controls, not as a sizing metric for a business case.
The same caution applies to incident headlines. An Orca Security page in the supplied material references “144 Mastra npm Packages Compromised,” but the extract provides no incident timeline, package names, or impact details. Do not put an unexplained incident count in an executive deck. Instead, translate the risk into a verifiable requirement: can your process stop a newly malicious package before it reaches a production artifact?
Use six coverage areas. They map to distinct assets and enforcement boundaries:
| Coverage area | What the control should find or enforce | Relevant boundary | Example evidence test |
|---|---|---|---|
| Code | Security defects, dangerous data flow, insecure AI-generated changes, policy violations | Pull request and protected branch | Open a PR with a known vulnerable code fixture and verify required-check behavior |
| Dependencies | Known vulnerabilities, malicious packages, license policy, prohibited package sources | Lockfile creation, build, and release | Add a prohibited test package and confirm the release job cannot proceed |
| Secrets | Tokens, private keys, credentials, and high-confidence leaked secrets | Commit, pull request, repository history, and build logs | Commit a revoked test token and measure detection, redaction, and bypass handling |
| Build | Compromised build inputs, unsafe runners, cache poisoning, unpinned actions | Workflow execution environment | Run an unpinned reusable action fixture and verify a blocking policy |
| Artifact | Image or package vulnerabilities, provenance, signatures, SBOM, immutable promotion | Registry and deployment handoff | Attempt deployment of an unsigned image digest |
| Pipeline control | Permissions, approvals, OIDC trust, protected environments, deployment admission, audit evidence | CI configuration through production admission | Attempt production deployment from a non-release branch or untrusted identity |
This layout prevents a common buying mistake: selecting a strong code scanner and discovering later that nobody owns artifact signing or deployment admission. OWASP’s CI/CD risk list explicitly includes third-party service usage, artifact integrity validation, and logging; those are reminders that the pipeline itself is an attack surface, not just a convenient place to run SAST.
Turn build and pipeline concerns into testable requirements
“Secure the pipeline” is too vague for a buying decision. Write checks that a security engineer can test in a sandbox repository and that a platform engineer can operate after purchase. For GitHub Actions, the following requirements are concrete enough to score.
- Reusable workflow pinning: require third-party actions and reusable workflows to use an immutable commit SHA, not a mutable tag such as
@v4. Decide whether internal reusable workflows may use protected tags, then test that the policy distinguishes the two cases. - Workflow permissions: require explicit
permissions:declarations. A typical build job should have onlycontents: read; a deploy job should receiveid-token: writeonly when it actually exchanges an OIDC token. - OIDC trust policy: require cloud trust policies to constrain issuer, repository, branch or environment, and audience. A token issued for
refs/heads/feature/testmust not assume the production deployment role. - Self-hosted runner isolation: require ephemeral runners for untrusted pull requests, no shared workspace between jobs, and no production cloud credentials on general-purpose runners. A persistent runner that executes both forked PRs and release jobs is a hard design failure.
- Cache poisoning resistance: prevent untrusted workflows from writing cache keys later restored by trusted workflows. Test a pull request attempting to write the exact cache key used by the release branch.
- Artifact attestations: require a signed attestation tied to an immutable image or package digest, source revision, and builder identity. A tag such as
prodis not sufficient evidence because it can be moved. - Deployment admission: verify the signature, provenance predicate, approved repository, and digest at the cluster or deployment platform. A scanner that blocks a CI job but has no admission control cannot stop a manually pushed artifact.
Cosign is evaluated here for signing and verification workflows, not for source-code scanning. OPA-based policy engines are evaluated for policy decisions and admission rules, not for vulnerability research. JFrog Xray is evaluated for repository and artifact-risk workflows, while a code security product is evaluated for code and secret analysis. Put that layer distinction directly in the matrix.
Use one score per requirement, then name the responsible control
Score the combined toolchain, not individual products in isolation. A requirement receives one score after you identify every control involved: for example, a GitHub Actions branch rule plus a third-party scanner can jointly provide a blocking pull-request gate. Do not add their scores together. The resulting score describes the requirement’s effective enforcement; the matrix still records which product or native CI control is responsible.
This avoids double-counting and exposes responsibility gaps. A code scanner may detect an issue, GitHub Actions may expose it as a check, and branch protection may make it required. If branch protection is not configured, the toolchain does not have a blocking gate regardless of the scanner’s marketing claims.
| Score | Testable meaning at the relevant boundary |
|---|---|
| 0 | No detection or enforcement for the requirement. |
| 1 | Detects or reports the condition, but cannot block at the required boundary. Example: a PR comment exists, but merge and release can continue. |
| 2 | Can block only through a maintained custom integration, script, webhook, or manual approval process. Exceptions are outside the control or are not auditable. |
| 3 | Enforces at the required boundary through a supported integration or native platform control, and records an auditable, time-bounded exception with an approver. |
Weighted totals are useful for comparing two viable designs, but never let them override a release-critical gap. Mark any requirement that must be present before production release as a hard gate. A candidate fails if a hard gate scores below its minimum, even if it wins the weighted total.
Copy this CSV template into a spreadsheet. Create one row per requirement, not one row per product feature.
Requirement,Coverage area,Owner,Weight,Gate status,Evidence test,Candidate score,Enforcement point,False-positive results,Integration effort,Exception process Block critical code finding on protected PR,Code,AppSec lead,5,Hard gate: minimum 3,PR with approved vulnerable-code fixture,,,,, Block prohibited dependency before release,Dependencies,Build platform owner,5,Hard gate: minimum 3,Release build with prohibited package fixture,,,,, Detect and revoke committed test secret,Secrets,Security operations,4,Required: minimum 2,Commit revoked test token and inspect alert path,,,,, Require SHA-pinned external actions,Build,CI platform owner,4,Hard gate: minimum 3,Workflow using third-party @v4 tag,,,,, Require signed provenance for production image,Artifact,Release engineering,5,Hard gate: minimum 3,Deploy unsigned image digest,,,,, Restrict production OIDC role by repository and environment,Pipeline control,Cloud IAM owner,5,Hard gate: minimum 3,Exchange token from feature branch,,,,,
For weights, use 1 through 5. Calculate a candidate’s weighted score as sum(weight × score) / sum(weight × 3). Keep the raw score and hard-gate result beside the percentage; a tidy 84% does not make an unsigned production artifact acceptable.
Worked example: a 40-engineer GitHub Actions team
Consider a 40-engineer SaaS team using GitHub Actions, containers, a cloud OIDC deployment role, and Kubernetes. The team releases twice weekly and wants PR feedback within 12 minutes. Its non-negotiable conditions are: protected-branch code gating, SHA-pinned external actions, restricted production OIDC, and signed artifact admission.
The team tests two illustrative toolchains. These are completed example scores from the stated test design, not a claim that a product will produce the same result in every configuration.
- Candidate A: GitHub Actions native controls, GitHub Advanced Security, and Cosign. No Kubernetes admission policy is added.
- Candidate B: GitHub Actions native controls, Checkmarx for application-security testing, JFrog Xray for dependency/artifact workflows, Cosign, and an OPA-based Kubernetes admission policy.
| Requirement | Weight | Hard gate | Candidate A score / result | Candidate B score / result | Named owner |
|---|---|---|---|---|---|
| Block critical code finding on protected PR | 5 | Minimum 3 | 3 / pass | 3 / pass | AppSec lead |
| Block prohibited dependency before release | 5 | Minimum 3 | 2 / fail | 3 / pass | Build platform owner |
| Detect committed test secret and create auditable triage record | 4 | Minimum 2 | 3 / pass | 3 / pass | Security operations |
| Reject external action referenced by mutable tag | 4 | Minimum 3 | 3 / pass | 3 / pass | CI platform owner |
| Reject unsigned production image at deployment admission | 5 | Minimum 3 | 1 / fail | 3 / pass | Release engineering |
| Restrict production OIDC role to release environment | 5 | Minimum 3 | 3 / pass | 3 / pass | Cloud IAM owner |
| Weighted score | 28 total | All hard gates required | 80% / rejected | 100% / eligible | Security architect |
Candidate A is rejected despite an 80% weighted score. Its unsigned artifact check occurs before deployment and therefore detects the problem, but does not stop a manually pushed or otherwise unverified image from entering the cluster. Candidate B is eligible because its admission policy enforces the same requirement at the deployment boundary.
The second-order cost is important: Candidate B has more contracts, integrations, alert queues, and ownership boundaries. The decision is not “buy more tools.” It is “buy or build the minimum controls necessary to close hard gates, then refuse duplicate scanners unless they improve a scored requirement.”
Run a proof of coverage, not a polished vendor demo
A vendor demonstration usually starts with a preselected repository, a tuned ruleset, and an engineer who knows where every setting lives. Your trial should start with a disposable repository containing fixtures that represent your actual failure modes. Use revocable credentials, non-production cloud accounts, and intentionally vulnerable code that your legal and security teams approve for testing.
Set measurable success criteria before granting access:
- PR latency: record median and worst-case added time for a pull request scan. For the 40-engineer team, a 12-minute PR budget means a 15-minute required scan is not acceptable, even if its findings are useful.
- Triage volume: count findings from 20 representative repositories, then calculate how many require human review per week. Do not accept “high signal” as an answer without a sample result set.
- False-positive handling: verify whether a developer can suppress a finding, whether the suppression expires, and whether the approver, reason, and ticket are retained.
- Audit evidence: require a retrievable record containing commit SHA, workflow run, policy decision, artifact digest, signer or builder identity, approver, and exception expiry.
- Exception turnaround: test an urgent but legitimate release. Define whether the on-call security approver must respond within one hour, four business hours, or another service level.
- Operational recovery: disable the scanner or policy service in a test environment. Determine whether releases fail closed, fail open, or require an emergency bypass—and who can invoke it.
Record integration effort in engineer-days, including policy maintenance and identity configuration. A “native integration” may still require branch-protection changes, cloud IAM work, registry permissions, SIEM forwarding, and developer training. Those costs belong in the same decision sheet as the license proposal.
Build the matrix this week
Start with one production service and one CI platform. Do not inventory every security product first. Instead, schedule a 90-minute session with the people who can actually own the gates: an AppSec lead, CI platform owner, release engineer, cloud IAM owner, and an engineering manager representing developers.
- Copy the template and write six to ten requirements in boundary language: “reject unsigned image at admission,” not “support supply-chain security.”
- Assign exactly one named owner to every gate. Consulted teams can be listed elsewhere; one person must own evidence and exception handling.
- Mark release-critical rows as hard gates and set their minimum score, usually 3 for production deployment controls.
- Create a fixture repository with a leaked test secret, vulnerable code path, prohibited dependency, mutable action reference, untrusted OIDC request, poisoned-cache attempt, and unsigned image.
- Score each candidate toolchain only after running the fixtures. Attach links to workflow logs, policy decisions, and exception records as evidence.
- Reject any candidate with a hard-gate failure before discussing its weighted score, user interface, or suite discount.
The result is more useful than a generic top-tools list because it tells you what you are purchasing: a particular enforced outcome, at a particular boundary, owned by a particular team. That is the level of specificity required to prevent a CI/CD security program from becoming a collection of alerts that nobody can turn into a release decision.
For a baseline risk taxonomy, use the OWASP Top 10 CI/CD Security Risks. For dependency-risk context, review Sonatype’s CI/CD pipeline security material, but validate package-ecosystem coverage, policy behavior, and enforcement in your own repositories before treating any research headline as a procurement requirement.