Secure Supply Chain Consumption Framework
- Version: 2024
- URL: https://github.com/ossf/s2c2f
- Source of truth:
pipeline_check/core/standards/data/s2c2f.py
Microsoft / OpenSSF Secure Supply Chain Consumption Framework. Ingest, inventory, scan, rebuild, fix, the consumer-side controls for taking a third-party dependency safely.
At a glance
- Controls in this standard: 11
- Controls evidenced by at least one check: 11 / 11
- Distinct checks evidencing this standard: 134
- Of those, autofixable with
--fix: 33
How to read severity
Every check below ships at a fixed severity level. The scale is the same across providers and standards so a CRITICAL finding in one place means the same thing as a CRITICAL finding anywhere else.
| Level | What it means | Examples |
|---|---|---|
| CRITICAL | Active exploit primitive in the workflow as written. Treat as P0: a default scan path lands an attacker on a secret, an RCE, or production write access without further effort. | Hardcoded credential literal, branch ref pointing at a known-compromised action, signed-into-an-unverified registry. |
| HIGH | Production-impact gap that requires modest attacker effort or a second condition to weaponize. Remediate this sprint; the secondary condition is usually already present in real pipelines. | Action pinned to a floating tag, sensitive permissions on a low-popularity action, mutable container tag in prod. |
| MEDIUM | Significant defense-in-depth gap. Not directly exploitable on its own but disables a control whose absence widens the blast radius of a separate compromise. Backlog with a deadline. | Missing branch protection, container without resource limits, freshly-published dependency consumed before the cooldown window. |
| LOW | Hygiene / hardening issue. Not a vulnerability on its own but raises baseline posture and reduces audit friction. | Missing CI logging retention, SBOM without supplier attribution, ECR repo without scan-on-push. |
| INFO | Degraded-mode signal. The scanner couldn't reach an API or parse a config and surfaces the gap so the operator knows coverage was incomplete. No finding against the workload itself. | CB-000 CodeBuild API access failed, IAM-000 IAM enumeration failed. |
Coverage by control
Click a control ID to jump to the per-control section with the full check list. The severity mix column shows the spread of evidencing checks by severity (Critical / High / Medium / Low / Info).
| Control | Title | Checks | Severity mix |
|---|---|---|---|
ING-1 |
L1: Use package managers trusted by your organization | 24 | 15H · 8M · 1L |
ING-3 |
L1: Have the capability to deny-list specific vulnerable / malicious OSS | 1 | 1H |
SCA-1 |
L1: Scan OSS for known vulnerabilities | 12 | 1H · 11M |
SCA-3 |
L2: Scan OSS for malware | 7 | 7C |
UPD-1 |
L1: Update vulnerable OSS manually (pin + track versions) | 38 | 23H · 10M · 5L |
UPD-2 |
L3: Enable automated OSS updates (Dependabot / Renovate) | 6 | 6M |
ENF-1 |
L2: Enforce security policy of OSS usage (block on violation) | 13 | 3H · 10M |
ENF-2 |
L2: Break the build when a violation is detected | 4 | 1H · 3M |
REB-2 |
L4: Digitally sign rebuilt / produced OSS artifacts | 16 | 2H · 14M |
REB-3 |
L4: Generate SBOMs for artifacts produced | 11 | 1H · 9M · 1L |
REB-4 |
L4: Digitally sign SBOMs produced (attested provenance) | 9 | 9M |
Filter at runtime
Restrict a scan to checks that evidence this standard with --standard s2c2f:
# All providers, only checks tied to this standard
pipeline_check --standard s2c2f
# Compose with --pipeline to scope by provider
pipeline_check --pipeline github --standard s2c2f
# Compose with another standard to widen the lens
pipeline_check --pipeline aws --standard s2c2f --standard owasp_cicd_top_10
Controls in scope
ING-1: L1: Use package managers trusted by your organization
Evidenced by 24 checks across 12 providers (AWS, Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, Dockerfile, GitHub Actions, GitLab CI, Helm, Jenkins, Tekton).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-018 |
Package install from insecure source | HIGH | Azure DevOps | 🔧 fix |
ADO-028 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | Azure DevOps | |
ARGO-008 |
Argo script source pipes remote install or disables TLS | HIGH | Argo Workflows | 🔧 fix |
BB-014 |
Package install from insecure source | HIGH | Bitbucket | 🔧 fix |
BB-027 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | Bitbucket | |
BK-004 |
Remote script piped into shell interpreter | HIGH | Buildkite | 🔧 fix |
BK-008 |
TLS verification disabled in step command | MEDIUM | Buildkite | 🔧 fix |
CA-002 |
CodeArtifact repository has a public external connection | HIGH | AWS | |
CC-018 |
Package install from insecure source | HIGH | CircleCI | 🔧 fix |
CC-028 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | CircleCI | |
DF-001 |
FROM image not pinned to sha256 digest | HIGH | Dockerfile | 🔧 fix |
DF-003 |
ADD pulls remote URL without integrity verification | HIGH | Dockerfile | |
DF-004 |
RUN executes a remote script via curl-pipe / wget-pipe | HIGH | Dockerfile | |
ECR-006 |
ECR pull-through cache rule uses an untrusted upstream | HIGH | AWS | |
GHA-018 |
Package install from insecure source | HIGH | GitHub Actions | 🔧 fix |
GHA-029 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | GitHub Actions | |
GL-018 |
Package install from insecure source | HIGH | GitLab CI | 🔧 fix |
GL-027 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | GitLab CI | |
HELM-001 |
Chart.yaml declares legacy apiVersion: v1 | MEDIUM | Helm | 🔧 fix |
HELM-003 |
Chart dependency declared on a non-HTTPS repository | HIGH | Helm | 🔧 fix |
HELM-009 |
Chart home / sources URL uses a non-HTTPS scheme | LOW | Helm | |
JF-018 |
Package install from insecure source | HIGH | Jenkins | 🔧 fix |
JF-031 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | Jenkins | |
TKN-008 |
Tekton step script pipes remote install or disables TLS | HIGH | Tekton | 🔧 fix |
ING-3: L1: Have the capability to deny-list specific vulnerable / malicious OSS
Evidenced by 1 check across AWS.
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
CA-002 |
CodeArtifact repository has a public external connection | HIGH | AWS |
SCA-1: L1: Scan OSS for known vulnerabilities
Evidenced by 12 checks across 11 providers (AWS, Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, GitHub Actions, GitLab CI, Jenkins, Tekton).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-020 |
No vulnerability scanning step | MEDIUM | Azure DevOps | |
ARGO-012 |
No vulnerability scanning step | MEDIUM | Argo Workflows | |
BB-015 |
No vulnerability scanning step | MEDIUM | Bitbucket | |
BK-012 |
No vulnerability scanning step | MEDIUM | Buildkite | |
CC-020 |
No vulnerability scanning step | MEDIUM | CircleCI | |
ECR-001 |
Image scanning on push not enabled | HIGH | AWS | |
ECR-007 |
Inspector v2 enhanced scanning disabled for ECR | MEDIUM | AWS | |
GCB-008 |
No vulnerability scanning step in Cloud Build pipeline | MEDIUM | Cloud Build | |
GHA-020 |
No vulnerability scanning step | MEDIUM | GitHub Actions | |
GL-019 |
No vulnerability scanning step | MEDIUM | GitLab CI | |
JF-020 |
No vulnerability scanning step | MEDIUM | Jenkins | |
TKN-012 |
No vulnerability scanning step | MEDIUM | Tekton |
SCA-3: L2: Scan OSS for malware
Evidenced by 7 checks across 7 providers (AWS, Azure DevOps, Bitbucket, CircleCI, GitHub Actions, GitLab CI, Jenkins).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-026 |
Pipeline contains indicators of malicious activity | CRITICAL | Azure DevOps | |
BB-025 |
Pipeline contains indicators of malicious activity | CRITICAL | Bitbucket | |
CB-011 |
CodeBuild buildspec contains indicators of malicious activity | CRITICAL | AWS | |
CC-026 |
Config contains indicators of malicious activity | CRITICAL | CircleCI | |
GHA-027 |
Workflow contains indicators of malicious activity | CRITICAL | GitHub Actions | |
GL-025 |
Pipeline contains indicators of malicious activity | CRITICAL | GitLab CI | |
JF-029 |
Jenkinsfile contains indicators of malicious activity | CRITICAL | Jenkins |
UPD-1: L1: Update vulnerable OSS manually (pin + track versions)
Evidenced by 38 checks across 13 providers (AWS, Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, Dockerfile, GitHub Actions, GitLab CI, Helm, Jenkins, Tekton).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-001 |
Task reference not pinned to specific version | HIGH | Azure DevOps | 🔧 fix |
ADO-005 |
Container image not pinned to specific version | HIGH | Azure DevOps | |
ADO-009 |
Container image pinned by tag rather than sha256 digest | LOW | Azure DevOps | |
ADO-021 |
Package install without lockfile enforcement | MEDIUM | Azure DevOps | 🔧 fix |
ADO-025 |
Cross-repo template not pinned to commit SHA | HIGH | Azure DevOps | |
ARGO-001 |
Argo template container image not pinned to a digest | HIGH | Argo Workflows | |
BB-001 |
pipe: action not pinned to exact version | HIGH | Bitbucket | 🔧 fix |
BB-009 |
pipe: pinned by version rather than sha256 digest | LOW | Bitbucket | |
BB-021 |
Package install without lockfile enforcement | MEDIUM | Bitbucket | 🔧 fix |
BK-001 |
Buildkite plugin not pinned to an exact version | HIGH | Buildkite | |
CB-005 |
Outdated managed build image | MEDIUM | AWS | |
CB-009 |
CodeBuild image not pinned by digest | MEDIUM | AWS | |
CC-001 |
Orb not pinned to exact semver | HIGH | CircleCI | 🔧 fix |
CC-003 |
Docker image not pinned by digest | HIGH | CircleCI | |
CC-021 |
Package install without lockfile enforcement | MEDIUM | CircleCI | 🔧 fix |
CC-029 |
Machine executor image not pinned | HIGH | CircleCI | |
DF-001 |
FROM image not pinned to sha256 digest | HIGH | Dockerfile | 🔧 fix |
DF-003 |
ADD pulls remote URL without integrity verification | HIGH | Dockerfile | |
DF-010 |
apt-get dist-upgrade / upgrade pulls unknown package versions | LOW | Dockerfile | |
DF-011 |
Package manager install without cache cleanup in same layer | LOW | Dockerfile | |
ECR-002 |
Image tags are mutable | HIGH | AWS | |
GCB-001 |
Cloud Build step image not pinned by digest | HIGH | Cloud Build | 🔧 fix |
GHA-001 |
Action not pinned to commit SHA | HIGH | GitHub Actions | 🔧 fix |
GHA-021 |
Package install without lockfile enforcement | MEDIUM | GitHub Actions | 🔧 fix |
GHA-025 |
Reusable workflow not pinned to commit SHA | HIGH | GitHub Actions | |
GL-001 |
Image not pinned to specific version or digest | HIGH | GitLab CI | 🔧 fix |
GL-005 |
include: pulls remote / project without pinned ref | HIGH | GitLab CI | |
GL-009 |
Image pinned to version tag rather than sha256 digest | LOW | GitLab CI | |
GL-021 |
Package install without lockfile enforcement | MEDIUM | GitLab CI | 🔧 fix |
GL-028 |
services: image not pinned | HIGH | GitLab CI | |
GL-030 |
trigger: include: pulls child pipeline without pinned ref | HIGH | GitLab CI | |
HELM-002 |
Chart.lock missing per-dependency digests | HIGH | Helm | 🔧 fix |
HELM-004 |
Chart dependency version is a range, not an exact pin | MEDIUM | Helm | |
HELM-008 |
Chart.lock generated more than 90 days ago | MEDIUM | Helm | |
JF-001 |
Shared library not pinned to a tag or commit | HIGH | Jenkins | |
JF-009 |
Agent docker image not pinned to sha256 digest | HIGH | Jenkins | |
JF-021 |
Package install without lockfile enforcement | MEDIUM | Jenkins | 🔧 fix |
TKN-001 |
Tekton step image not pinned to a digest | HIGH | Tekton |
UPD-2: L3: Enable automated OSS updates (Dependabot / Renovate)
Evidenced by 6 checks across 6 providers (Azure DevOps, Bitbucket, CircleCI, GitHub Actions, GitLab CI, Jenkins).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-022 |
Dependency update command bypasses lockfile pins | MEDIUM | Azure DevOps | 🔧 fix |
BB-022 |
Dependency update command bypasses lockfile pins | MEDIUM | Bitbucket | 🔧 fix |
CC-022 |
Dependency update command bypasses lockfile pins | MEDIUM | CircleCI | 🔧 fix |
GHA-022 |
Dependency update command bypasses lockfile pins | MEDIUM | GitHub Actions | 🔧 fix |
GL-022 |
Dependency update command bypasses lockfile pins | MEDIUM | GitLab CI | 🔧 fix |
JF-022 |
Dependency update command bypasses lockfile pins | MEDIUM | Jenkins | 🔧 fix |
ENF-1: L2: Enforce security policy of OSS usage (block on violation)
Evidenced by 13 checks across 8 providers (AWS, Azure DevOps, Bitbucket, Buildkite, CircleCI, GitHub Actions, GitLab CI, Jenkins).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-004 |
Deployment job missing environment binding | MEDIUM | Azure DevOps | |
BB-004 |
Deploy step missing deployment: environment gate |
MEDIUM | Bitbucket | |
BK-007 |
Deploy step not gated by a manual block / input | MEDIUM | Buildkite | |
BK-013 |
Deploy step has no branches: filter | MEDIUM | Buildkite | |
CB-008 |
CodeBuild buildspec is inline (not sourced from a protected repo) | HIGH | AWS | |
CC-009 |
Deploy job missing manual approval gate | MEDIUM | CircleCI | |
CD-002 |
AllAtOnce deployment config, no canary or rolling strategy | HIGH | AWS | |
CP-001 |
No approval action before deploy stages | HIGH | AWS | |
CP-005 |
Production Deploy stage has no preceding ManualApproval | MEDIUM | AWS | |
GHA-014 |
Deploy job missing environment binding | MEDIUM | GitHub Actions | 🔧 fix |
GL-004 |
Deploy job lacks manual approval or environment gate | MEDIUM | GitLab CI | |
JF-005 |
Deploy stage missing manual input approval |
MEDIUM | Jenkins | |
JF-024 |
input approval step missing submitter restriction |
MEDIUM | Jenkins |
ENF-2: L2: Break the build when a violation is detected
Evidenced by 4 checks across 2 providers (AWS, GitLab CI).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
CP-001 |
No approval action before deploy stages | HIGH | AWS | |
CP-005 |
Production Deploy stage has no preceding ManualApproval | MEDIUM | AWS | |
GL-004 |
Deploy job lacks manual approval or environment gate | MEDIUM | GitLab CI | |
GL-029 |
Manual deploy job defaults to allow_failure: true | MEDIUM | GitLab CI |
REB-2: L4: Digitally sign rebuilt / produced OSS artifacts
Evidenced by 16 checks across 11 providers (AWS, Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, GitHub Actions, GitLab CI, Jenkins, Tekton).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-006 |
Artifacts not signed | MEDIUM | Azure DevOps | |
ARGO-009 |
Artifacts not signed (no cosign/sigstore step) | MEDIUM | Argo Workflows | |
BB-006 |
Artifacts not signed | MEDIUM | Bitbucket | |
BK-009 |
Artifacts not signed (no cosign/sigstore step) | MEDIUM | Buildkite | |
CA-001 |
CodeArtifact domain not encrypted with customer KMS CMK | MEDIUM | AWS | |
CC-006 |
Artifacts not signed (no cosign/sigstore step) | MEDIUM | CircleCI | |
CP-002 |
Artifact store not encrypted with customer-managed KMS key | MEDIUM | AWS | |
ECR-005 |
Repository encrypted with AES256 rather than KMS CMK | MEDIUM | AWS | |
GCB-009 |
Artifacts not signed (no cosign / sigstore step) | MEDIUM | Cloud Build | |
GHA-006 |
Artifacts not signed (no cosign/sigstore step) | MEDIUM | GitHub Actions | |
GL-006 |
Artifacts not signed | MEDIUM | GitLab CI | |
JF-006 |
Artifacts not signed | MEDIUM | Jenkins | |
LMB-001 |
Lambda function has no code-signing config | HIGH | AWS | |
SIGN-001 |
No AWS Signer profile defined for Lambda deploys | MEDIUM | AWS | |
SIGN-002 |
AWS Signer profile is revoked or inactive | HIGH | AWS | |
TKN-009 |
Artifacts not signed (no cosign/sigstore step) | MEDIUM | Tekton |
REB-3: L4: Generate SBOMs for artifacts produced
Evidenced by 11 checks across 11 providers (Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, Dockerfile, GitHub Actions, GitLab CI, Helm, Jenkins, Tekton).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-007 |
SBOM not produced | MEDIUM | Azure DevOps | |
ARGO-010 |
No SBOM generated for build artifacts | MEDIUM | Argo Workflows | |
BB-007 |
SBOM not produced | MEDIUM | Bitbucket | |
BK-010 |
No SBOM generated for build artifacts | MEDIUM | Buildkite | |
CC-007 |
SBOM not produced (no CycloneDX/syft/Trivy-SBOM step) | MEDIUM | CircleCI | |
DF-016 |
Image lacks OCI provenance labels | LOW | Dockerfile | |
GHA-007 |
SBOM not produced (no CycloneDX/syft/Trivy-SBOM step) | MEDIUM | GitHub Actions | |
GL-007 |
SBOM not produced | MEDIUM | GitLab CI | |
HELM-002 |
Chart.lock missing per-dependency digests | HIGH | Helm | 🔧 fix |
JF-007 |
SBOM not produced | MEDIUM | Jenkins | |
TKN-010 |
No SBOM generated for build artifacts | MEDIUM | Tekton |
REB-4: L4: Digitally sign SBOMs produced (attested provenance)
Evidenced by 9 checks across 9 providers (Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, GitHub Actions, GitLab CI, Jenkins, Tekton).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-024 |
No SLSA provenance attestation produced | MEDIUM | Azure DevOps | |
ARGO-011 |
No SLSA provenance attestation produced | MEDIUM | Argo Workflows | |
BB-024 |
No SLSA provenance attestation produced | MEDIUM | Bitbucket | |
BK-011 |
No SLSA provenance attestation produced | MEDIUM | Buildkite | |
CC-024 |
No SLSA provenance attestation produced | MEDIUM | CircleCI | |
GHA-024 |
No SLSA provenance attestation produced | MEDIUM | GitHub Actions | |
GL-024 |
No SLSA provenance attestation produced | MEDIUM | GitLab CI | |
JF-028 |
No SLSA provenance attestation produced | MEDIUM | Jenkins | |
TKN-011 |
No SLSA provenance attestation produced | MEDIUM | Tekton |
Check details
Every check that evidences this standard, rendered once with its detection mechanism, recommendation, and any known false-positive modes or real-world incident references. The per-control tables above link to the matching block here.
ADO-001: Task reference not pinned to specific version HIGH 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Floating-major task references (@1, @2) can roll forward silently when the task publisher ships a breaking or malicious update. Pass when every task: reference carries a two- or three-segment semver.
Recommendation. Reference tasks by a full semver (DownloadSecureFile@1.2.3) or extension-published-version. Track task updates explicitly via Azure DevOps extension settings rather than letting @1 drift.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: ADO-001 in the Azure DevOps provider.
ADO-004: Deployment job missing environment binding MEDIUM
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation).
How this is detected. Without an environment: binding, ADO cannot enforce approvals, checks, or deployment history against a named resource. Every deployment: job should bind one.
Recommendation. Add environment: <name> to every deployment: job. Configure approvals, required branches, and business-hours checks on the matching Environment in the ADO UI.
Source: ADO-004 in the Azure DevOps provider.
ADO-005: Container image not pinned to specific version HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Container images can be declared at resources.containers[].image or job.container (string or {image:}). Floating / untagged refs let the publisher swap the image contents.
Recommendation. Reference images by @sha256:<digest> or at minimum a full immutable version tag. Avoid :latest and untagged refs.
Source: ADO-005 in the Azure DevOps provider.
ADO-006: Artifacts not signed MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Passes when cosign / sigstore / slsa-* / notation-sign appears anywhere in the pipeline text.
Recommendation. Add a task that runs cosign sign or notation sign, Azure Pipelines' workload identity federation enables keyless signing. Publish the signature to the artifact feed and verify it at deploy time.
Source: ADO-006 in the Azure DevOps provider.
ADO-007: SBOM not produced MEDIUM
Evidences: REB-3 L4: Generate SBOMs for artifacts produced.
How this is detected. Without an SBOM, downstream consumers can't audit the dependency set shipped in the artifact.
Recommendation. Add an SBOM step, microsoft/sbom-tool, syft . -o cyclonedx-json, or anchore/sbom-action. Publish the SBOM as a pipeline artifact so downstream consumers can ingest it.
Source: ADO-007 in the Azure DevOps provider.
ADO-009: Container image pinned by tag rather than sha256 digest LOW
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. ADO-005 fails floating tags at HIGH; ADO-009 is the stricter tier. Even immutable-looking version tags can be repointed by registry operators.
Recommendation. Resolve each image to its current digest and replace the tag with @sha256:<digest>. Schedule regular digest bumps via Renovate or a scheduled pipeline.
Source: ADO-009 in the Azure DevOps provider.
ADO-018: Package install from insecure source HIGH 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Detects package-manager invocations that use plain HTTP registries (--index-url http://, --registry=http://) or disable TLS verification (--trusted-host, --no-verify) in a pipeline. These patterns allow man-in-the-middle injection of malicious packages.
Recommendation. Use HTTPS registry URLs. Remove --trusted-host and --no-verify flags. Pin to a private registry with TLS.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: ADO-018 in the Azure DevOps provider.
ADO-020: No vulnerability scanning step MEDIUM
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. Without a vulnerability scanning step, known-vulnerable dependencies ship to production undetected. The check recognises trivy, grype, snyk, npm audit, yarn audit, safety check, pip-audit, osv-scanner, and govulncheck.
Recommendation. Add a vulnerability scanning step, trivy, grype, snyk test, npm audit, pip-audit, or osv-scanner. Publish results so vulnerabilities surface before deployment.
Source: ADO-020 in the Azure DevOps provider.
ADO-021: Package install without lockfile enforcement MEDIUM 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Detects package-manager install commands that do not enforce a lockfile or hash verification. Without lockfile enforcement the resolver pulls whatever version is currently latest, exactly the window a supply-chain attacker exploits.
Recommendation. Use lockfile-enforcing install commands: npm ci instead of npm install, pip install --require-hashes -r requirements.txt, yarn install --frozen-lockfile, bundle install --frozen, and go install tool@v1.2.3.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: ADO-021 in the Azure DevOps provider.
ADO-022: Dependency update command bypasses lockfile pins MEDIUM 🔧 fix
Evidences: UPD-2 L3: Enable automated OSS updates (Dependabot / Renovate).
How this is detected. Detects pip install --upgrade, npm update, yarn upgrade, bundle update, cargo update, go get -u, and composer update. These commands bypass lockfile pins and pull whatever version is currently latest. Tooling upgrades (pip install --upgrade pip) are exempted.
Recommendation. Remove dependency-update commands from CI. Use lockfile-pinned install commands (npm ci, pip install -r requirements.txt) and update dependencies via a dedicated PR pipeline (e.g. Dependabot, Renovate).
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Known false positives.
- Common build-tool bootstrapping idioms (
pip install --upgrade pip,pip install --upgrade setuptools wheel virtualenv) and security-tool installs (pip install --upgrade pip-audit / cyclonedx-bom / semgrep) are exempted by theDEP_UPDATE_REtooling allowlist. Other tooling-upgrade idioms not yet on the list can still trip the rule. Defaults to MEDIUM confidence so CI gates can require--min-confidence HIGHto ignore.
Source: ADO-022 in the Azure DevOps provider.
ADO-024: No SLSA provenance attestation produced MEDIUM
Evidences: REB-4 L4: Digitally sign SBOMs produced (attested provenance).
How this is detected. On Azure Pipelines the common pattern is a Bash@3 task invoking cosign attest --yes --predicate=provenance.json $(image). The native Microsoft SBOM tool emits _manifest/spdx_2.2/manifest.spdx.json for SBOM but does not produce provenance on its own.
Recommendation. Add a task that runs cosign attest against a provenance.intoto.jsonl statement, or Microsoft's sbom-tool in attestation mode. ADO-006 covers signing; this rule covers the in-toto statement SLSA Build L3 additionally requires.
Source: ADO-024 in the Azure DevOps provider.
ADO-025: Cross-repo template not pinned to commit SHA HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Azure Pipelines resolves template: build.yml@tools against the tools repo resource's ref: field. When that ref is refs/heads/main (or missing, which defaults to the pipeline's default branch), a push to the callee repo changes what your pipeline runs on the next invocation.
Recommendation. On every resources.repositories entry referenced from a template: ...@repo-alias directive, set ref: refs/tags/<sha> or the bare 40-char commit SHA, never a branch or floating tag. A moved branch/tag swaps the template body without changing your pipeline file.
Source: ADO-025 in the Azure DevOps provider.
ADO-026: Pipeline contains indicators of malicious activity CRITICAL
Evidences: SCA-3 L2: Scan OSS for malware.
How this is detected. ADO pipelines can run arbitrary shell via bash / script / powershell tasks. This rule scans every string value for known-bad patterns (reverse shells, base64-decoded execution, miner binaries, exfil channels). Orthogonal to ADO-016/ADO-017/ADO-023.
Recommendation. Treat as a potential compromise. Identify the PR/branch that added the matching task(s), rotate any Service Connections the pipeline can reach, and audit Pipeline run logs for outbound traffic to the matched hosts.
Known false positives.
- Security-training repositories, CTF challenges, and red-team exercise pipelines legitimately contain reverse-shell strings or exfil domains as literals. Matches inside YAML keys / HCL attributes whose names contain
example,fixture,sample,demo, ortestare auto-suppressed; bare lines in a production pipeline still fire. - Defaults to LOW confidence. Filter with
--min-confidence MEDIUMto ignore all matches; the rule still surfaces the hit for teams that want to spot-check.
Source: ADO-026 in the Azure DevOps provider.
ADO-028: Package install bypasses registry integrity (git / path / tarball source) MEDIUM
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Complements ADO-021 (missing lockfile flag). Git URL installs without a commit pin, local-path installs, and direct tarball URLs bypass the registry integrity controls the lockfile relies on.
Recommendation. Pin git dependencies to a commit SHA. Publish private packages to an internal registry (Azure Artifacts) instead of installing from a filesystem path or tarball URL.
Source: ADO-028 in the Azure DevOps provider.
ARGO-001: Argo template container image not pinned to a digest HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Walks spec.templates[].container, spec.templates[].script, and spec.templates[].containerSet.containers[]. The image must contain @sha256: followed by a 64-char hex digest.
Recommendation. Pin every container / script template image to a content-addressable digest (alpine@sha256:<digest>). Tag-only references (alpine:3.18) and rolling tags (alpine:latest) let a compromised registry update redirect the workflow's containers at the next pull, with no audit trail in the WorkflowTemplate.
Source: ARGO-001 in the Argo Workflows provider.
ARGO-008: Argo script source pipes remote install or disables TLS HIGH 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Walks script.source and joined container.args text with the cross-provider CURL_PIPE_RE and TLS_BYPASS_RE regexes.
Recommendation. Replace curl ... | sh with a download-then-verify-then-execute pattern. Drop TLS-bypass flags (curl -k, git config http.sslverify false); install the missing CA into the template image instead. Both forms let an attacker controlling DNS / a transparent proxy substitute the script the workflow runs.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: ARGO-008 in the Argo Workflows provider.
ARGO-009: Artifacts not signed (no cosign/sigstore step) MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Detection mirrors GHA-006 / TKN-009 / BK-009, the shared signing-token catalog (cosign, sigstore, slsa-github-generator, slsa-framework, notation-sign) is searched across every string in each Argo document. Fires only on artifact-producing Workflows / WorkflowTemplates (those that invoke docker build / docker push / kaniko / helm upgrade / aws s3 sync / etc.) so lint-only Workflows don't trip it.
Recommendation. Add a cosign step to the Workflow. The most common shape is a final sign template that runs cosign sign --yes <repo>@sha256:<digest> after the build. Sign by digest, not tag, so a re-pushed tag can't bypass the signature.
Source: ARGO-009 in the Argo Workflows provider.
ARGO-010: No SBOM generated for build artifacts MEDIUM
Evidences: REB-3 L4: Generate SBOMs for artifacts produced.
How this is detected. An SBOM (CycloneDX or SPDX) records every component baked into the build. Without one, post-incident triage can't answer did this CVE ship? for a given artifact. Detection uses the shared SBOM-token catalog: syft, cyclonedx, cdxgen, spdx-tools, microsoft/sbom-tool. Fires only on artifact-producing Workflows.
Recommendation. Add an SBOM-generation template. syft <artifact> -o cyclonedx-json > /tmp/sbom.json runs in any standard container; cyclonedx-cli and cdxgen are alternative producers. Persist the SBOM as an output artifact so downstream templates and consumers can read it.
Source: ARGO-010 in the Argo Workflows provider.
ARGO-011: No SLSA provenance attestation produced MEDIUM
Evidences: REB-4 L4: Digitally sign SBOMs produced (attested provenance).
How this is detected. Provenance generation is distinct from signing. A signed artifact proves who published it; a provenance attestation proves where / how it was built. Detection uses the shared provenance-token catalog (slsa-framework, cosign attest, in-toto, witness run, attest-build-provenance).
Recommendation. Add a cosign attest --predicate slsa.json --type slsaprovenance <ref> step after the build template, or use witness run to record the build environment. Publish the attestation alongside the artifact so consumers can verify how it was built, not just who signed it.
Source: ARGO-011 in the Argo Workflows provider.
ARGO-012: No vulnerability scanning step MEDIUM
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. Vulnerability scanning sits at a different layer from signing and SBOM. It answers does this artifact ship a known CVE? rather than can we verify what it is?. Detection uses the shared vuln-scan-token catalog: trivy, grype, snyk, npm-audit, pip-audit, osv-scanner, govulncheck, anchore, codeql-action, semgrep, bandit, checkov, tfsec. Walks every Argo document and passes if any document includes a scanner reference.
Recommendation. Add a vulnerability scanner template. trivy fs /workdir for source / filesystem; trivy image <ref> for container images. grype, snyk, npm audit, pip-audit are alternatives. Fail the template on findings above a chosen severity so a regression blocks the merge instead of shipping.
Source: ARGO-012 in the Argo Workflows provider.
BB-001: pipe: action not pinned to exact version HIGH 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Bitbucket pipes are docker-image references. Major-only (:1) or missing tags let Atlassian/the publisher swap the image contents. Full semver or sha256 digest is required.
Recommendation. Pin every pipe: to a full semver tag (e.g. atlassian/aws-s3-deploy:1.4.0) or to an immutable SHA. Floating majors like :1 can roll to new code silently.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: BB-001 in the Bitbucket provider.
BB-004: Deploy step missing deployment: environment gate MEDIUM
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation).
How this is detected. A step whose name or invoked pipe matches deploy / release / publish / promote should declare a deployment: field so Bitbucket enforces deployment-scoped variables, approvals, and history.
Recommendation. Add deployment: production (or staging / test) to the step. Configure the matching environment in the repo's Deployments settings with required reviewers and secured variables.
Source: BB-004 in the Bitbucket provider.
BB-006: Artifacts not signed MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Unsigned artifacts can't be verified downstream. Passes when cosign / sigstore / slsa-* / notation-sign appears in the pipeline body.
Recommendation. Add a step that runs cosign sign against the built image or archive, using Bitbucket OIDC for keyless signing where possible. Publish the signature next to the artifact and verify it at deploy time.
Source: BB-006 in the Bitbucket provider.
BB-007: SBOM not produced MEDIUM
Evidences: REB-3 L4: Generate SBOMs for artifacts produced.
How this is detected. Without an SBOM, downstream consumers can't audit the dependency set shipped in the artifact. Passes when CycloneDX / syft / anchore / sbom-tool / Trivy-SBOM appears.
Recommendation. Add an SBOM step, syft . -o cyclonedx-json, Trivy with --format cyclonedx, or Microsoft's sbom-tool. Attach the SBOM as a build artifact.
Source: BB-007 in the Bitbucket provider.
BB-009: pipe: pinned by version rather than sha256 digest LOW
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. BB-001 fails floating tags at HIGH; BB-009 is the stricter tier. Even immutable-looking semver tags can be repointed by the registry; sha256 digests are tamper-evident.
Recommendation. Resolve each pipe to its digest (docker buildx imagetools inspect bitbucketpipelines/<name>:<ver>) and reference it via @sha256:<digest>.
Source: BB-009 in the Bitbucket provider.
BB-014: Package install from insecure source HIGH 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Detects package-manager invocations that use plain HTTP registries (--index-url http://, --registry=http://) or disable TLS verification (--trusted-host, --no-verify) in a pipeline. These patterns allow man-in-the-middle injection of malicious packages.
Recommendation. Use HTTPS registry URLs. Remove --trusted-host and --no-verify flags. Pin to a private registry with TLS.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: BB-014 in the Bitbucket provider.
BB-015: No vulnerability scanning step MEDIUM
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. Without a vulnerability scanning step, known-vulnerable dependencies ship to production undetected. The check recognises trivy, grype, snyk, npm audit, yarn audit, safety check, pip-audit, osv-scanner, and govulncheck.
Recommendation. Add a vulnerability scanning step, trivy, grype, snyk test, npm audit, pip-audit, or osv-scanner. Publish results so vulnerabilities surface before deployment.
Source: BB-015 in the Bitbucket provider.
BB-021: Package install without lockfile enforcement MEDIUM 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Detects package-manager install commands that do not enforce a lockfile or hash verification. Without lockfile enforcement the resolver pulls whatever version is currently latest, exactly the window a supply-chain attacker exploits.
Recommendation. Use lockfile-enforcing install commands: npm ci instead of npm install, pip install --require-hashes -r requirements.txt, yarn install --frozen-lockfile, bundle install --frozen, and go install tool@v1.2.3.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: BB-021 in the Bitbucket provider.
BB-022: Dependency update command bypasses lockfile pins MEDIUM 🔧 fix
Evidences: UPD-2 L3: Enable automated OSS updates (Dependabot / Renovate).
How this is detected. Detects pip install --upgrade, npm update, yarn upgrade, bundle update, cargo update, go get -u, and composer update. These commands bypass lockfile pins and pull whatever version is currently latest. Tooling upgrades (pip install --upgrade pip) are exempted.
Recommendation. Remove dependency-update commands from CI. Use lockfile-pinned install commands (npm ci, pip install -r requirements.txt) and update dependencies via a dedicated PR pipeline (e.g. Dependabot, Renovate).
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Known false positives.
- Common build-tool bootstrapping idioms (
pip install --upgrade pip,pip install --upgrade setuptools wheel virtualenv) and security-tool installs (pip install --upgrade pip-audit / cyclonedx-bom / semgrep) are exempted by theDEP_UPDATE_REtooling allowlist. Other tooling-upgrade idioms not yet on the list can still trip the rule. Defaults to MEDIUM confidence so CI gates can require--min-confidence HIGHto ignore.
Source: BB-022 in the Bitbucket provider.
BB-024: No SLSA provenance attestation produced MEDIUM
Evidences: REB-4 L4: Digitally sign SBOMs produced (attested provenance).
How this is detected. Bitbucket has no native SLSA builder; self-hosted attestation via cosign attest or witness run is the usual path. Pipes like atlassian/cosign-attest (if published) would also match.
Recommendation. Add a step that runs cosign attest against a provenance.intoto.jsonl statement, or integrate the TestifySec witness run attestor. Artifact signing alone (BB-006) doesn't satisfy SLSA Build L3.
Source: BB-024 in the Bitbucket provider.
BB-025: Pipeline contains indicators of malicious activity CRITICAL
Evidences: SCA-3 L2: Scan OSS for malware.
How this is detected. Specific indicators only (reverse shells, base64-decoded execution, miner binaries, Discord/Telegram webhooks, credential-dump pipes, audit-erasure commands). Does not replace BB-014 (TLS bypass) or BB-013 (Docker insecure), those are hygiene; this is evidence.
Recommendation. Treat as a potential compromise. Identify the PR that added the matching step(s), rotate any credentials referenced from the pipeline's variable groups, and audit recent builds.
Known false positives.
- Security-training repositories, CTF challenges, and red-team exercise pipelines legitimately contain reverse-shell strings or exfil domains as literals. Matches inside YAML keys / HCL attributes whose names contain
example,fixture,sample,demo, ortestare auto-suppressed; bare lines in a production pipeline still fire. - Defaults to LOW confidence. Filter with
--min-confidence MEDIUMto ignore all matches; the rule still surfaces the hit for teams that want to spot-check.
Source: BB-025 in the Bitbucket provider.
BB-027: Package install bypasses registry integrity (git / path / tarball source) MEDIUM
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Complements BB-021 (missing lockfile flag). Git URL installs without a commit pin, local-path installs, and direct tarball URLs bypass the registry integrity controls the lockfile relies on.
Recommendation. Pin git dependencies to a commit SHA. Publish private packages to an internal registry instead of installing from a filesystem path or tarball URL.
Source: BB-027 in the Bitbucket provider.
BK-001: Buildkite plugin not pinned to an exact version HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Buildkite resolves plugin refs at agent boot. foo#v1.2.3 locks the version; foo#main / foo does not. Detection fires on bare names, branch keywords, and partial-semver pins (v4, v4.13).
Recommendation. Pin every plugin reference to an exact tag (docker-compose#v4.13.0) or a 40-char commit SHA. Bare references (docker-compose), branch refs (#main / #master), and major-only floats (#v4) resolve to whatever is current at agent start time, which lets a compromised plugin release execute inside the pipeline.
Source: BK-001 in the Buildkite provider.
BK-004: Remote script piped into shell interpreter HIGH 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. The detection fires on curl|bash, curl|sh, wget|bash, iex (iwr ...), and the corresponding Invoke-WebRequest|Invoke-Expression PowerShell forms. Use curl -fsSLO <url>; sha256sum -c install.sh.sha256; bash install.sh instead.
Recommendation. Download the installer to disk, verify a checksum or signature, then execute it. curl ... | sh lets the remote host change what runs in your pipeline at any time, and any TLS / DNS error during download silently feeds a partial script to the shell.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: BK-004 in the Buildkite provider.
BK-007: Deploy step not gated by a manual block / input MEDIUM
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation).
How this is detected. A step is treated as a deploy when its label, key, or any command line contains a deploy keyword (deploy, ship, release, promote, apply, rollout, terraform apply, kubectl apply, helm upgrade, aws ecs update-service). The check passes when at least one preceding step in the same pipeline file is a block: or input: flow-control step.
Recommendation. Insert a - block: "Deploy?" (or - input: step) in front of every deploy step. Buildkite waits for a human to click Unblock before the gated steps run, which prevents an unreviewed merge from auto-deploying to production. Combine with branches: main so the gate only appears on release branches.
Known false positives.
- Pipelines where the deploy gate lives in a triggered pipeline rather than the local file, the local pipeline looks ungated even though the actual deploy is gated downstream. Add a no-op
block:to silence.
Source: BK-007 in the Buildkite provider.
BK-008: TLS verification disabled in step command MEDIUM 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Detection fires on the canonical bypass flags across curl, wget, git, npm, pip, gcloud, and openssl. The check is deliberately conservative, partial-word matches (--insecure-protocols) are excluded.
Recommendation. Drop curl -k / --insecure, wget --no-check-certificate, git -c http.sslVerify=false, and pip install --trusted-host. If a CA isn't trusted, install it into the agent's trust store (update-ca-certificates) rather than disabling validation pipeline-wide. A compromised intermediate that strips TLS gets a free hand with every fetch the step performs.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: BK-008 in the Buildkite provider.
BK-009: Artifacts not signed (no cosign/sigstore step) MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Unsigned artifacts can't be verified downstream, a tampered build is indistinguishable from a legitimate one. The check recognises cosign, sigstore, slsa-github-generator, slsa-framework, and notation-sign as signing tools, matching the shared signing-token catalog used by the other CI packs.
Recommendation. Add a signing step, install cosign once (brew install cosign in the agent image, or a cosign-install plugin) and call cosign sign --yes <ref> after the build. For container images pushed to ECR / GCR / GHCR, the same call signs by digest. Publish the signature alongside the artifact and verify it at consumption time.
Source: BK-009 in the Buildkite provider.
BK-010: No SBOM generated for build artifacts MEDIUM
Evidences: REB-3 L4: Generate SBOMs for artifacts produced.
How this is detected. An SBOM (CycloneDX or SPDX) records every component baked into the build. Without one, post-incident triage can't answer did this CVE ship? for a given artifact. Detection uses the shared SBOM-token catalog, syft, cyclonedx, cdxgen, spdx-tools, microsoft/sbom-tool.
Recommendation. Add an SBOM-generation step. syft <artifact> -o cyclonedx-json > sbom.json runs in any standard agent image; cyclonedx-cli and cdxgen are alternative producers. Upload the SBOM via buildkite-agent artifact upload so downstream consumers (and incident-response tooling) can match deployed artifacts to the components they were built from.
Source: BK-010 in the Buildkite provider.
BK-011: No SLSA provenance attestation produced MEDIUM
Evidences: REB-4 L4: Digitally sign SBOMs produced (attested provenance).
How this is detected. Provenance generation is distinct from signing. A signed artifact proves who published it; a provenance attestation proves where / how it was built. Without it, a leaked signing key forges identity but a leaked build environment also forges provenance. You need both for the SLSA L3 non-falsifiability guarantee. Detection uses the shared provenance-token catalog (slsa-framework, cosign attest, in-toto, attest-build-provenance).
Recommendation. Run cosign attest --predicate slsa.json (or the SLSA-framework generator from a build-time step) after the build completes. The predicate records the build inputs and the agent that produced the artifact. Publish the attestation alongside the artifact so consumers can verify how it was built, not just who signed it.
Source: BK-011 in the Buildkite provider.
BK-012: No vulnerability scanning step MEDIUM
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. Vulnerability scanning sits at a different layer from signing and SBOM. It answers does this artifact ship a known CVE? rather than can we verify what it is?. Detection uses the shared vuln-scan-token catalog: trivy, grype, snyk, npm-audit, pip-audit, anchore, dependency-check, checkov, semgrep.
Recommendation. Add a vulnerability scanner, trivy fs . for source / filesystem, trivy image <ref> for container images, grype and snyk for either. Add npm audit / pip-audit for language-specific dep audits. Fail the step on findings above a chosen severity so a regression blocks the merge instead of shipping.
Source: BK-012 in the Buildkite provider.
BK-013: Deploy step has no branches: filter MEDIUM
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation).
How this is detected. A step is treated as a deploy when its label, key, or any command line contains a deploy keyword (deploy, ship-it, release, promote, rollout, helm upgrade, kubectl apply, terraform apply, aws ecs update-service, aws lambda update-function-code, gcloud run deploy). The check passes when the step declares branches: with at least one literal branch name (a wildcard like "*" is treated as an explicit opt-out, not a passing filter, and still trips). The pipeline-level default also counts, top-level steps: with branches: propagates.
Recommendation. Add branches: "main release/*" (or your release branch glob) to every deploy step. Buildkite skips the step on any other branch, which prevents a feature-branch PR from accidentally promoting code to production. Combine with BK-007's manual block: so a release branch plus a human approval is the path to deploy.
Known false positives.
- Trunk-based teams that branch-protect
mainand treat every merge as a deploy candidate may not usebranches:. Addbranches: mainto make the policy explicit, or ignore BK-013 in.pipeline-check-ignore.ymlwith a scope ofmain-only repos.
Source: BK-013 in the Buildkite provider.
CA-001: CodeArtifact domain not encrypted with customer KMS CMK MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. AWS-owned encryption (the default alias/aws/codeartifact key) keeps the key policy under AWS's control, not yours. That's fine for confidentiality but means cross-account auditability of every Decrypt event lives with AWS, and you can't revoke or scope key access without recreating the domain. A customer-managed CMK puts both controls back in your hands.
Recommendation. Recreate the CodeArtifact domain with an encryption-key argument pointing at a customer-managed CMK. Domain encryption is set at creation and cannot be changed after.
Source: CA-001 in the AWS provider.
CA-002: CodeArtifact repository has a public external connection HIGH
Evidences: ING-1 L1: Use package managers trusted by your organization, ING-3 L1: Have the capability to deny-list specific vulnerable / malicious OSS.
How this is detected. An external connection to public:npmjs / public:pypi / public:nuget / public:maven-central fetches packages from the public registry on first resolution. A typo-squat (request vs requests) or a compromised upstream lands in the cache the first time anyone names it; every subsequent build pulls the cached substitute. The pull-through cache with an allow-list is the same risk shape solved by an explicit allowlist.
Recommendation. Route public package consumption through a pull-through cache repository governed by an allow-list of package names, and point build-time repos at that cache rather than directly at public:npmjs/public:pypi. Unscoped public upstreams expose builds to dependency-confusion and typosquatting attacks.
Source: CA-002 in the AWS provider.
CB-005: Outdated managed build image MEDIUM
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Only AWS-managed aws/codebuild/standard:N.0 images are version-checked. Custom or third-party images pass here, CB-009 handles the separate concern of tag vs digest pinning for custom images.
Recommendation. Update the CodeBuild environment image to aws/codebuild/standard:7.0 or later to ensure the build environment receives the latest security patches.
Known false positives.
- One version behind the current
aws/codebuild/standardis a hygiene warning, not a production issue, and defaults to MEDIUM confidence. The rule emits HIGH only when the project is two or more versions behind. Custom or third-party images are not version-checked here; CB-009 handles tag-vs-digest pinning for those.
Source: CB-005 in the AWS provider.
CB-008: CodeBuild buildspec is inline (not sourced from a protected repo) HIGH
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation).
How this is detected. An inline buildspec (source.buildspec set to YAML text, or a S3 URL) bypasses the protections that cover your source code. A user with codebuild:UpdateProject can rewrite the build commands without touching the repository, no PR review, no branch protection, no audit of what changed. Store buildspec.yml in the repo instead.
Recommendation. Remove the inline buildspec and store buildspec.yml in the source repository under branch protection. Anyone with codebuild:UpdateProject can silently rewrite an inline buildspec; repository-sourced buildspecs inherit the repo's review and protection controls.
Source: CB-008 in the AWS provider.
CB-009: CodeBuild image not pinned by digest MEDIUM
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. CodeBuild pulls the environment image on every build. A tag pointer can be moved by whoever controls the registry; a digest cannot. AWS-managed aws/codebuild/... images are exempt. Those are covered by CB-005 and are not part of the tag-mutation threat model.
Recommendation. Pin custom CodeBuild images by @sha256:<digest>. Tag-based references (:latest, :1.2.3) can be silently overwritten to point at a malicious layer that is pulled on the next build.
Source: CB-009 in the AWS provider.
CB-011: CodeBuild buildspec contains indicators of malicious activity CRITICAL
Evidences: SCA-3 L2: Scan OSS for malware.
How this is detected. Scans the source.buildspec text on every CodeBuild project for concrete attack indicators: reverse shells, base64-decoded execution, miner binaries/pools, Discord/Telegram webhooks, credential-dump pipes, audit-erasure commands. CB-011 is CRITICAL by design, a true positive is evidence of compromise, not a hygiene improvement. Repo-sourced buildspecs (not inlined) return NOT APPLICABLE because the text isn't visible to the scanner; CB-008 already flags the inline form as a governance gap.
Recommendation. Treat as a potential compromise. Identify which principal or pipeline ran the CodeBuild project recently, rotate its service role's credentials, audit CloudTrail for outbound activity to the matched hosts, and, if an inline buildspec is in use (CB-008), enforce repo-sourced buildspecs under branch protection so the next malicious edit requires a PR.
Known false positives.
- Security-training repositories, CTF challenges, and red-team exercise pipelines legitimately contain reverse-shell strings or exfil domains as literals. Matches inside YAML keys / HCL attributes whose names contain
example,fixture,sample,demo, ortestare auto-suppressed; bare lines in a production pipeline still fire. - Defaults to LOW confidence. Filter with
--min-confidence MEDIUMto ignore all matches; the rule still surfaces the hit for teams that want to spot-check.
Source: CB-011 in the AWS provider.
CC-001: Orb not pinned to exact semver HIGH 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Orb references in the orbs: block must include an @x.y.z suffix to lock a specific version. References without @, with @volatile, or with only a major (@1) or major.minor (@5.1) version float and can silently pull in malicious updates.
Recommendation. Pin every orb to an exact semver version (circleci/node@5.1.0). Floating references like @volatile, @1, or bare names without @ resolve to whatever is latest at build time, allowing a compromised orb update to execute in the pipeline.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: CC-001 in the CircleCI provider.
CC-003: Docker image not pinned by digest HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Docker images referenced in docker: blocks under jobs or executors must include an @sha256:... digest suffix. Tag-only references (:latest, :18) are mutable and can be replaced at any time by whoever controls the upstream registry.
Recommendation. Pin every Docker image to its sha256 digest: cimg/node:18@sha256:abc123.... Tags like :latest or :18 are mutable, a registry compromise or upstream push silently replaces the image content.
Source: CC-003 in the CircleCI provider.
CC-006: Artifacts not signed (no cosign/sigstore step) MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Unsigned artifacts cannot be verified downstream, so a tampered build is indistinguishable from a legitimate one. The check recognises cosign, sigstore, slsa-framework, and notation-sign as signing tools.
Recommendation. Add a signing step to the pipeline, e.g. install cosign and run cosign sign, or use the sigstore CLI. Publish the signature alongside the artifact and verify it at consumption time.
Source: CC-006 in the CircleCI provider.
CC-007: SBOM not produced (no CycloneDX/syft/Trivy-SBOM step) MEDIUM
Evidences: REB-3 L4: Generate SBOMs for artifacts produced.
How this is detected. Without an SBOM, downstream consumers cannot audit the exact set of dependencies shipped in the artifact, delaying vulnerability response when a transitive dep is disclosed. The check recognises CycloneDX, syft, Anchore SBOM action, spdx-sbom-generator, Microsoft sbom-tool, and Trivy in SBOM mode.
Recommendation. Add an SBOM generation step, syft . -o cyclonedx-json, Trivy with --format cyclonedx, or Microsoft's sbom-tool. Attach the SBOM to the build artifacts so consumers can ingest it into their vulnerability management pipeline.
Source: CC-007 in the CircleCI provider.
CC-009: Deploy job missing manual approval gate MEDIUM
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation).
How this is detected. In CircleCI, manual approval is implemented by adding a job with type: approval to the workflow and making the deploy job require it. Without this gate, any push to the triggering branch deploys immediately with no human review.
Recommendation. Add a type: approval job that precedes the deploy job in the workflow, and list it in the deploy job's requires:. This ensures a human must click Approve in the CircleCI UI before production changes roll out.
Source: CC-009 in the CircleCI provider.
CC-018: Package install from insecure source HIGH 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Detects package-manager invocations that use plain HTTP registries (--index-url http://, --registry=http://) or disable TLS verification (--trusted-host, --no-verify) in a CircleCI config. These patterns allow man-in-the-middle injection of malicious packages.
Recommendation. Use HTTPS registry URLs. Remove --trusted-host and --no-verify flags. Pin to a private registry with TLS.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: CC-018 in the CircleCI provider.
CC-020: No vulnerability scanning step MEDIUM
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. Without a vulnerability scanning step, known-vulnerable dependencies ship to production undetected. The check recognises trivy, grype, snyk, npm audit, yarn audit, safety check, pip-audit, osv-scanner, and govulncheck.
Recommendation. Add a vulnerability scanning step, trivy, grype, snyk test, npm audit, pip-audit, or osv-scanner. Publish results so vulnerabilities surface before deployment.
Source: CC-020 in the CircleCI provider.
CC-021: Package install without lockfile enforcement MEDIUM 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Detects package-manager install commands that do not enforce a lockfile or hash verification. Without lockfile enforcement the resolver pulls whatever version is currently latest, exactly the window a supply-chain attacker exploits.
Recommendation. Use lockfile-enforcing install commands: npm ci instead of npm install, pip install --require-hashes -r requirements.txt, yarn install --frozen-lockfile, bundle install --frozen, and go install tool@v1.2.3.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: CC-021 in the CircleCI provider.
CC-022: Dependency update command bypasses lockfile pins MEDIUM 🔧 fix
Evidences: UPD-2 L3: Enable automated OSS updates (Dependabot / Renovate).
How this is detected. Detects pip install --upgrade, npm update, yarn upgrade, bundle update, cargo update, go get -u, and composer update. These commands bypass lockfile pins and pull whatever version is currently latest. Tooling upgrades (pip install --upgrade pip) are exempted.
Recommendation. Remove dependency-update commands from CI. Use lockfile-pinned install commands (npm ci, pip install -r requirements.txt) and update dependencies via a dedicated PR workflow (e.g. Dependabot, Renovate).
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Known false positives.
- Common build-tool bootstrapping idioms (
pip install --upgrade pip,pip install --upgrade setuptools wheel virtualenv) and security-tool installs (pip install --upgrade pip-audit / cyclonedx-bom / semgrep) are exempted by theDEP_UPDATE_REtooling allowlist. Other tooling-upgrade idioms not yet on the list can still trip the rule. Defaults to MEDIUM confidence so CI gates can require--min-confidence HIGHto ignore.
Source: CC-022 in the CircleCI provider.
CC-024: No SLSA provenance attestation produced MEDIUM
Evidences: REB-4 L4: Digitally sign SBOMs produced (attested provenance).
How this is detected. Signing (cosign sign) binds identity to bytes; attestation (cosign attest) binds a structured claim about how the artifact was built. SLSA verifiers check the latter so consumers can enforce builder/source/parameter policies.
Recommendation. Add a run: cosign attest command against a provenance.intoto.jsonl statement, or use the circleci/attestation orb. CC-006 covers signing; this rule covers the build-provenance step SLSA Build L3 requires.
Source: CC-024 in the CircleCI provider.
CC-026: Config contains indicators of malicious activity CRITICAL
Evidences: SCA-3 L2: Scan OSS for malware.
How this is detected. Fires on concrete indicators only (reverse shells, base64-decoded execution, miner binaries, Discord/Telegram webhooks, webhook.site callbacks, credential-dump pipes, history-erasure).
Recommendation. Treat as a potential compromise. Identify the PR that added the matching step(s), rotate any contexts/env vars the pipeline can reach, and audit recent CircleCI runs for outbound traffic to the matched hosts.
Known false positives.
- Security-training repositories, CTF challenges, and red-team exercise pipelines legitimately contain reverse-shell strings or exfil domains as literals. Matches inside YAML keys / HCL attributes whose names contain
example,fixture,sample,demo, ortestare auto-suppressed; bare lines in a production pipeline still fire. - Defaults to LOW confidence. Filter with
--min-confidence MEDIUMto ignore all matches; the rule still surfaces the hit for teams that want to spot-check.
Source: CC-026 in the CircleCI provider.
CC-028: Package install bypasses registry integrity (git / path / tarball source) MEDIUM
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Complements CC-021 (missing lockfile flag). Git URL installs without a commit pin, local-path installs, and direct tarball URLs bypass the registry integrity controls the lockfile relies on.
Recommendation. Pin git dependencies to a commit SHA. Publish private packages to an internal registry instead of installing from a filesystem path or tarball URL.
Source: CC-028 in the CircleCI provider.
CC-029: Machine executor image not pinned HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. CC-003 covers Docker images declared under docker: blocks. It does not reach the machine executor, where the image is on machine.image. A rolling tag (current, edge, default) pulls a fresh image whenever CircleCI publishes one, reintroducing the same supply-chain risk Docker-image pinning is designed to eliminate.
Recommendation. Pin every machine.image to a dated release tag, ubuntu-2204:2024.05.1 rather than :current, :edge, :default, or a bare image name. CircleCI rotates the current / edge aliases on its own cadence, so builds re-run on an image the author never reviewed.
Source: CC-029 in the CircleCI provider.
CD-002: AllAtOnce deployment config, no canary or rolling strategy HIGH
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation).
How this is detected. AllAtOnce shifts 100% of traffic to the new revision in one step. There's no gradient to halt on if a CloudWatch alarm trips mid-rollout, the bad revision is already serving every request. Canary / linear configs introduce the shift-then-watch shape that lets monitors catch a regression before it's universal.
Recommendation. Switch to a canary or linear deployment configuration (e.g. CodeDeployDefault.LambdaCanary10Percent5Minutes or a custom rolling config) so that defects are caught before they affect all instances or traffic.
Source: CD-002 in the AWS provider.
CP-001: No approval action before deploy stages HIGH
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation), ENF-2 L2: Break the build when a violation is detected.
How this is detected. A pipeline that goes Source -> Build -> Deploy with no Approval action means every commit on the source branch ships, with no human ack between code-merged and code-running-in-prod. The Manual approval action is the intentional pause point, combine with CP-005 for production-tagged stages specifically.
Recommendation. Add a Manual approval action to a stage that precedes every Deploy stage that targets a production or sensitive environment.
Source: CP-001 in the AWS provider.
CP-002: Artifact store not encrypted with customer-managed KMS key MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. The pipeline's S3 artifact store holds intermediate build outputs handed between stages. Default SSE-S3 (AES256) encrypts at rest but uses an AWS-owned key whose policy you can't scope. A customer-managed CMK gives the same key-policy + CloudTrail Decrypt-event audit story you'd apply to Lambda code, Secrets Manager, or any other build output.
Recommendation. Configure a customer-managed AWS KMS key as the encryptionKey for each artifact store. This enables key rotation, fine-grained access policies, and CloudTrail auditing of decrypt operations.
Source: CP-002 in the AWS provider.
CP-005: Production Deploy stage has no preceding ManualApproval MEDIUM
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation), ENF-2 L2: Break the build when a violation is detected.
How this is detected. The complement to CP-001: this rule fires only on stages whose name contains prod / production / live. Even teams that intentionally skip approvals for dev / staging deploys usually want a human in the loop for a production-tagged target.
Recommendation. Add a Manual approval action immediately before any stage whose name contains prod / production. CP-001 covers the generic case; this rule specifically looks at production-tagged stages where the blast radius of an unreviewed deploy is largest.
Source: CP-005 in the AWS provider.
DF-001: FROM image not pinned to sha256 digest HIGH 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization, UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Reuses _primitives/image_pinning.classify so the floating-tag semantics match GL-001 / JF-009 / ADO-009 / CC-003. PINNED_TAG (e.g. python:3.12.1-slim) is treated as unpinned here too, only an explicit @sha256: survives, since the tag is mutable on the registry side.
Recommendation. Resolve every base image to its current digest (docker buildx imagetools inspect <ref> prints it) and pin via FROM repo@sha256:<digest>. Automate refreshes with Renovate or Dependabot. A floating tag (:latest, :3, no tag) silently swaps the build base under every rebuild.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Seen in the wild.
- Docker Hub typosquatting / namespace-takeover incidents (2017 onward): docker-library Sysdig and Aqua research documented thousands of malicious images uploaded under near-miss names (
alpinevsalphine, etc.) and occasional namespace recoveries shipping crypto-miners downstream. Digest-pinned consumers are immune; tag-pinned consumers pull whatever sits under the name today. - Codecov
codecov/codecov-actiontag-mutation incident (post-Codecov-Bash-uploader compromise): the upstream rotated the action's@v3tag during the fallout, and consumers pinning to the tag silently re-ran a different build than before. Digest pinning would have surfaced the change as a checksum mismatch instead of a silent swap.
Source: DF-001 in the Dockerfile provider.
DF-003: ADD pulls remote URL without integrity verification HIGH
Evidences: ING-1 L1: Use package managers trusted by your organization, UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. ADD with a URL is the historical Dockerfile footgun: it fetches at build time over HTTP(S) with no checksum and no signature, and the registry tag does not pin the source. A tampered server or DNS hijack silently swaps the content. COPY is for local files; RUN curl + verify is for remote ones.
Recommendation. Replace ADD https://... with a multi-step RUN: download the file with curl -fsSLo, verify a known-good checksum (sha256sum -c) or signature (cosign verify-blob), then extract / install. Better still: download the artifact in a builder stage and COPY it across. That way the verifier runs once at build time, not per-pull.
Source: DF-003 in the Dockerfile provider.
DF-004: RUN executes a remote script via curl-pipe / wget-pipe HIGH
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Reuses _primitives/remote_script_exec.scan so the vocabulary matches the equivalent CI-side rules (GHA-016, GL-016, BB-012, ADO-016, CC-016, JF-016).
Recommendation. Download to a file, verify checksum or signature, then execute. curl -fsSL <url> -o /tmp/x.sh && sha256sum -c <(echo '<digest> /tmp/x.sh') && bash /tmp/x.sh. Vendor installers from well-known hosts (rustup.rs, get.docker.com, ...) are reported with vendor_trusted=true so reviewers can calibrate.
Source: DF-004 in the Dockerfile provider.
DF-010: apt-get dist-upgrade / upgrade pulls unknown package versions LOW
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Running apt-get upgrade (or dist-upgrade) inside a Dockerfile is the classic pet-vs-cattle anti-pattern. Two back-to-back builds with the same Dockerfile can produce different images because the upstream archive moved between the two RUN invocations. dist-upgrade additionally relaxes dependency resolution. It can install / remove arbitrary packages to satisfy upgrades, so the resulting image's package set isn't even bounded by what the Dockerfile declares.
Recommendation. Drop the upgrade step. Build on a recent base image instead (rebuild your image when the base image gets a security patch, pin the base by digest per DF-001 so the rebuild is deterministic). apt-get install pkg=<version> for specific packages stays reproducible; upgrade / dist-upgrade does not.
Source: DF-010 in the Dockerfile provider.
DF-011: Package manager install without cache cleanup in same layer LOW
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Each Dockerfile RUN produces a layer. Installing packages in one layer and cleaning the cache in a later layer leaves the cache files in the lower layer forever, final image size is unchanged and the residual files broaden the attack surface (e.g. apt's signed-by keys, package metadata). The fix is layout, not behavior: do install + cleanup in the same RUN.
Recommendation. Combine the install and cleanup into the same RUN so the cache lands in a single layer that gets discarded together. Idiomatic pattern: RUN apt-get update && apt-get install -y <pkgs> && rm -rf /var/lib/apt/lists/*. Equivalent forms: apk add --no-cache <pkgs>, dnf install -y … && dnf clean all, yum install -y … && yum clean all, zypper -n in … && zypper clean -a.
Source: DF-011 in the Dockerfile provider.
DF-016: Image lacks OCI provenance labels LOW
Evidences: REB-3 L4: Generate SBOMs for artifacts produced.
How this is detected. The OCI image-spec annotation set is a small de facto standard maintained by the OCI working group. Only image.source and image.revision are checked because they're the two whose absence makes incident response materially harder; image.title / image.description are nice-to-have but the rule doesn't fire on those.
Recommendation. Add a LABEL line carrying at least org.opencontainers.image.source (the URL of the source repo) and org.opencontainers.image.revision (the commit SHA built into the image). Most registries surface those fields in the UI and on manifest inspect, which closes the source-to-image gap that GHA-006 / SLSA Build-L2 provenance attestation also addresses.
Known false positives.
- A multi-stage build's intermediate stages don't need provenance labels, only the final image ships. The rule fires per Dockerfile, not per stage; suppress for files where the final
FROMis intentional throwaway scratch.
Source: DF-016 in the Dockerfile provider.
ECR-001: Image scanning on push not enabled HIGH
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. scan-on-push runs a CVE check against the image's OS package layers at the moment it lands in ECR. Without it, an image with a known CVE deploys silently. The ECR basic scanner is free; ECR-007 covers the Inspector v2 enhanced scanner that adds language-ecosystem CVEs (npm, pip, gem).
Recommendation. Enable imageScanningConfiguration.scanOnPush on the repository. Consider also enabling Amazon Inspector continuous scanning for ongoing CVE detection against images already in the registry.
Source: ECR-001 in the AWS provider.
ECR-002: Image tags are mutable HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Mutable tags mean :latest, :v1.0, and :stable can be re-pushed silently, the same tag points to different image content over time. Pinning by digest (sha256:...) in deployment manifests is the only durable reference; IMMUTABLE on the repo enforces the property registry-side so a forgotten digest reference doesn't drift.
Recommendation. Set imageTagMutability=IMMUTABLE on the repository. Reference images by digest (sha256:...) in deployment manifests for strongest immutability guarantees.
Source: ECR-002 in the AWS provider.
ECR-005: Repository encrypted with AES256 rather than KMS CMK MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Same shape as CP-002 / CWL-002 / CCM-002: AES256 (the AWS-managed default) gives confidentiality at rest but no key-policy or CloudTrail Decrypt-event story. Container images are arguably sensitive intellectual property, the same key-policy + audit shape as build outputs in S3 is warranted.
Recommendation. Set encryptionType=KMS with a customer-managed key ARN.
Source: ECR-005 in the AWS provider.
ECR-006: ECR pull-through cache rule uses an untrusted upstream HIGH
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. AWS supports pull-through cache for ECR Public, Quay, K8s, GitHub Container Registry, GitLab, and Docker Hub. A rule pointing at registry-1.docker.io without an authenticated credential silently caches whatever the public namespace resolves to.
Recommendation. Scope pull-through cache rules to AWS-trusted registries (ECR Public, Quay.io with authentication, or a vetted private registry). Avoid wildcard or unauthenticated upstreams, a malicious image there gets cached into your account registry on first pull.
Source: ECR-006 in the AWS provider.
ECR-007: Inspector v2 enhanced scanning disabled for ECR MEDIUM
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. ECR-001's basic on-push scan covers OS-level packages, apt / yum / apk lineage. Most production CVE risk is in language ecosystems (npm, pip, gem, mvn) which the basic scanner ignores. Inspector v2 enhanced scanning closes that gap and runs continuously, so a CVE published two weeks after a build still surfaces against the deployed image.
Recommendation. Enable Amazon Inspector v2 for the ECR scan type on this account. Basic ECR scanning on-push only covers OS packages; Inspector v2 enhanced scanning adds language-ecosystem CVEs and runs continuously as new vulnerabilities are published.
Source: ECR-007 in the AWS provider.
GCB-001: Cloud Build step image not pinned by digest HIGH 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Bare references (gcr.io/cloud-builders/docker) are treated as :latest by Cloud Build. Tag-only references (:20, :latest) count as unpinned. Only @sha256:… suffixes pass.
Recommendation. Pin every steps[].name image to an @sha256:<digest> suffix. gcr.io/cloud-builders/docker:latest is mutable; Google publishes new builder images frequently and the next build would pull whatever is current. Resolve the digest with gcloud artifacts docker images describe <ref> --format='value(image_summary.digest)' and pin it.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: GCB-001 in the Cloud Build provider.
GCB-008: No vulnerability scanning step in Cloud Build pipeline MEDIUM
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. The detector matches tool names anywhere in the document, step images, args, or entrypoint strings. Container Analysis API scanning configured at the project level counts as compensating control but is out of scope for this YAML-only check; if you rely on it, suppress this rule via --checks.
Recommendation. Add a step that runs a vulnerability scanner, trivy, grype, snyk test, npm audit, pip-audit, osv-scanner, or govulncheck. In Cloud Build this typically looks like a step with name: aquasec/trivy or an entrypoint: bash step that invokes trivy image / grype <ref> on the built image.
Source: GCB-008 in the Cloud Build provider.
GCB-009: Artifacts not signed (no cosign / sigstore step) MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Silent-pass when the pipeline does not appear to produce artifacts (no docker push / gcloud run deploy / kubectl apply / etc. in any step). The detector matches cosign, sigstore, slsa-framework, and notation.
Recommendation. Add a signing step before images: is resolved, for example, a step with name: gcr.io/projectsigstore/cosign that runs cosign sign --yes <registry>/<repo>@<digest>. Pair with an attestation step (cosign attest --predicate sbom.json --type cyclonedx) so consumers can verify both the signature and the build provenance.
Source: GCB-009 in the Cloud Build provider.
GHA-001: Action not pinned to commit SHA HIGH 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Every uses: reference should pin a specific 40-char commit SHA. Tag and branch refs (@v4, @main) can be silently moved to malicious commits by whoever controls the upstream repository, a third-party action compromise will propagate into the pipeline on the next run.
Recommendation. Replace tag/branch references (@v4, @main) with the full 40-char commit SHA. Use Dependabot or StepSecurity to keep the pins fresh.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Seen in the wild.
- tj-actions/changed-files compromise (CVE-2025-30066, March 2025): a malicious commit retagged behind
@v1/@v45shipped CI-secret exfiltration to roughly 23,000 repos that had pinned the action to a mutable tag instead of a commit SHA. - reviewdog/action-setup compromise (CVE-2025-30154, March 2025): same week, similar mechanism. Tag-pinned consumers auto-pulled the malicious version; SHA-pinned consumers were unaffected.
Proof of exploit.
Tag-pinned reference (vulnerable):
- uses: tj-actions/changed-files@v45
Attack: the upstream maintainer (or anyone who compromises
the upstream repo) force-moves the v45 tag to a malicious
commit:
git tag -f v45
git push --force origin v45
Every consumer's next workflow run pulls the new code
automatically, executing the attacker's payload with the
job's secrets and GITHUB_TOKEN in scope.
Safe: pin to a 40-char commit SHA (immutable):
- uses: tj-actions/changed-files@a284dc1 # v45.0.0
Source: GHA-001 in the GitHub Actions provider.
GHA-006: Artifacts not signed (no cosign/sigstore step) MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Unsigned artifacts cannot be verified downstream, so a tampered build is indistinguishable from a legitimate one. The check recognizes cosign, sigstore, slsa-github-generator, slsa-framework, and notation-sign as signing tools.
Recommendation. Add a signing step, e.g. sigstore/cosign-installer followed by cosign sign, or slsa-framework/slsa-github-generator for keyless SLSA provenance. Publish the signature alongside the artifact and verify it at consumption time.
Seen in the wild.
- SolarWinds Orion compromise (December 2020): SUNBURST trojanized builds shipped to ~18,000 customers because no post-build signature could be checked against a trusted signing identity. Cryptographic signing on every release would have given downstream consumers a verifiable break with the upstream key, the absence of which was the ambient signal of compromise.
- PyTorch nightly compromise (December 2022): the
torchtritondependency was hijacked via PyPI dependency-confusion. Sigstore-style attestation tied to the official publisher would have made the impostor build fail verification rather than silently install.
Source: GHA-006 in the GitHub Actions provider.
GHA-007: SBOM not produced (no CycloneDX/syft/Trivy-SBOM step) MEDIUM
Evidences: REB-3 L4: Generate SBOMs for artifacts produced.
How this is detected. Without an SBOM, downstream consumers cannot audit the exact set of dependencies shipped in the artifact, delaying vulnerability response when a transitive dep is disclosed. The check recognises CycloneDX, syft, Anchore SBOM action, spdx-sbom-generator, Microsoft sbom-tool, and Trivy in SBOM mode.
Recommendation. Add an SBOM generation step, anchore/sbom-action, syft . -o cyclonedx-json, Trivy with --format cyclonedx, or Microsoft's sbom-tool. Attach the SBOM to the release so consumers can ingest it into their vuln-management pipeline.
Source: GHA-007 in the GitHub Actions provider.
GHA-014: Deploy job missing environment binding MEDIUM 🔧 fix
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation).
How this is detected. Without an environment: binding, a deploy job can't be gated by required reviewers, deployment-branch policies, or wait timers. Any push to the triggering branch will deploy immediately.
Recommendation. Add environment: <name> to jobs that deploy. Configure required reviewers, wait timers, and branch-protection rules on the matching GitHub environment.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Known false positives.
- Integration-test jobs that run
terraform applyorkubectl applyagainst a local mock (LocalStack, Moto, kind, k3d) aren't real deploys. The rule auto-suppresses a step whose env carriesAWS_ENDPOINT_URLorKUBE_API_URLpointing at a localhost address.
Source: GHA-014 in the GitHub Actions provider.
GHA-018: Package install from insecure source HIGH 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Detects package-manager invocations that use plain HTTP registries (--index-url http://, --registry=http://) or disable TLS verification (--trusted-host, --no-verify) in a workflow. These patterns allow man-in-the-middle injection of malicious packages.
Recommendation. Use HTTPS registry URLs. Remove --trusted-host and --no-verify flags. Pin to a private registry with TLS.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: GHA-018 in the GitHub Actions provider.
GHA-020: No vulnerability scanning step MEDIUM
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. Without a vulnerability scanning step, known-vulnerable dependencies ship to production undetected. The check recognises trivy, grype, snyk, npm audit, yarn audit, safety check, pip-audit, osv-scanner, and govulncheck.
Recommendation. Add a vulnerability scanning step, trivy, grype, snyk test, npm audit, pip-audit, or osv-scanner. Publish results so vulnerabilities surface before deployment.
Source: GHA-020 in the GitHub Actions provider.
GHA-021: Package install without lockfile enforcement MEDIUM 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Detects package-manager install commands that do not enforce a lockfile or hash verification. Without lockfile enforcement the resolver pulls whatever version is currently latest, exactly the window a supply-chain attacker exploits.
Recommendation. Use lockfile-enforcing install commands: npm ci instead of npm install, pip install --require-hashes -r requirements.txt, yarn install --frozen-lockfile, bundle install --frozen, and go install tool@v1.2.3.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: GHA-021 in the GitHub Actions provider.
GHA-022: Dependency update command bypasses lockfile pins MEDIUM 🔧 fix
Evidences: UPD-2 L3: Enable automated OSS updates (Dependabot / Renovate).
How this is detected. Detects pip install --upgrade, npm update, yarn upgrade, bundle update, cargo update, go get -u, and composer update. These commands bypass lockfile pins and pull whatever version is currently latest. Tooling upgrades (pip install --upgrade pip) are exempted.
Recommendation. Remove dependency-update commands from CI. Use lockfile-pinned install commands (npm ci, pip install -r requirements.txt) and update dependencies via a dedicated PR workflow (e.g. Dependabot, Renovate).
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Known false positives.
- Common build-tool bootstrapping idioms (
pip install --upgrade pip,pip install --upgrade setuptools wheel virtualenv) and security-tool installs (pip install --upgrade pip-audit / cyclonedx-bom / semgrep) are exempted by theDEP_UPDATE_REtooling allowlist. Other tooling-upgrade idioms not yet on the list can still trip the rule. Defaults to MEDIUM confidence so CI gates can require--min-confidence HIGHto ignore.
Source: GHA-022 in the GitHub Actions provider.
GHA-024: No SLSA provenance attestation produced MEDIUM
Evidences: REB-4 L4: Digitally sign SBOMs produced (attested provenance).
How this is detected. Provenance generation is distinct from signing. A signed artifact proves who published it; a provenance attestation proves where/how it was built. Consumers can then verify the build happened on a trusted runner, from a specific source commit, with known parameters. Without it, a leaked signing key forges identity but a leaked build environment also forges provenance. You need both for the SLSA L3 non-falsifiability guarantee.
Recommendation. Call slsa-framework/slsa-github-generator or actions/attest-build-provenance after the build step to emit an in-toto attestation alongside the artifact. cosign sign alone (covered by GHA-006) signs the artifact but doesn't record how it was built. SLSA Build L3 requires the provenance statement.
Source: GHA-024 in the GitHub Actions provider.
GHA-025: Reusable workflow not pinned to commit SHA HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. A reusable workflow runs with the caller's GITHUB_TOKEN and secrets by default. If uses: org/repo/.github/workflows/release.yml@v1 resolves to an attacker-modified commit, their code executes with your repository's permissions. This is the same threat model as unpinned step actions (GHA-001) but over a different uses: surface.
Recommendation. Pin every jobs.<id>.uses: reference to a 40-char commit SHA (owner/repo/.github/workflows/foo.yml@<sha>). Tag refs (@v1, @main) can be silently repointed by whoever controls the callee repository.
Source: GHA-025 in the GitHub Actions provider.
GHA-027: Workflow contains indicators of malicious activity CRITICAL
Evidences: SCA-3 L2: Scan OSS for malware.
How this is detected. Distinct from the hygiene checks. GHA-016 flags curl | bash as a risky default; this rule fires only on concrete indicators, reverse shells, base64-decoded execution, known miner binaries or pool URLs, exfil-channel domains, credential-dump pipes, history-erasure commands. Categories reported: obfuscated-exec, reverse-shell, crypto-miner, exfil-channel, credential-exfil, audit-erasure.
Recommendation. Treat this as a potential pipeline compromise. Inspect the matching step(s), identify the author and the PR that introduced them, rotate any credentials the workflow has access to, and audit CloudTrail/AuditLogs for exfil. If the match is a legitimate red-team exercise, whitelist via .pipelinecheckignore with an expires: date, never a permanent suppression.
Known false positives.
- Security-training repositories, CTF challenges, and red-team exercise workflows legitimately contain reverse-shell strings or exfil domains as literals. Matches inside YAML keys / HCL attributes whose names contain
example,fixture,sample,demo, ortestare auto-suppressed; bare lines in a production workflow still fire. - Defaults to LOW confidence. Filter with
--min-confidence MEDIUMto ignore all matches; the rule still surfaces the hit for teams that want to spot-check.
Source: GHA-027 in the GitHub Actions provider.
GHA-029: Package install bypasses registry integrity (git / path / tarball source) MEDIUM
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Package installs that pull from git+… without a pinned commit, from a local path (./dir, file:…, absolute paths), or from a direct tarball URL are invisible to the normal lockfile integrity controls. A moving branch head, a sibling checkout the build assumes exists, or a tarball whose hash isn't verified all give an attacker who controls any of those surfaces the ability to substitute code into the build.
Recommendation. Pin git dependencies to a commit SHA (pip install git+https://…/repo@<sha>, cargo install --git … --rev <sha>). Publish private packages to an internal registry instead of installing from a filesystem path or tarball URL.
Source: GHA-029 in the GitHub Actions provider.
GL-001: Image not pinned to specific version or digest HIGH 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Floating tags (latest or major-only) can be silently swapped under the job. Every image: reference should pin a specific version tag or digest.
Recommendation. Reference images by @sha256:<digest> or at minimum a full immutable version tag (e.g. python:3.12.1-slim). Avoid :latest and bare tags like :3.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: GL-001 in the GitLab CI provider.
GL-004: Deploy job lacks manual approval or environment gate MEDIUM
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation), ENF-2 L2: Break the build when a violation is detected.
How this is detected. A job whose stage or name contains deploy / release / publish / promote should either require manual approval or declare an environment: binding. Otherwise any push to the trigger branch ships to the target.
Recommendation. Add when: manual (optionally with rules: for protected branches) or bind the job to an environment: with a deployment tier so approvals and audit are enforced by GitLab's environment controls.
Source: GL-004 in the GitLab CI provider.
GL-005: include: pulls remote / project without pinned ref HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Cross-project and remote includes can be silently re-pointed. Branch-name refs (main/master/develop/head) are treated as unpinned; tag and SHA refs are considered safe.
Recommendation. Pin include: project: entries with ref: set to a tag or commit SHA. Avoid include: remote: for untrusted URLs; mirror the content into a trusted project and pin it.
Source: GL-005 in the GitLab CI provider.
GL-006: Artifacts not signed MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Unsigned artifacts can't be verified downstream, so a tampered build is indistinguishable from a legitimate one. Pass when any of cosign / sigstore / slsa-* / notation-sign appears in the pipeline text.
Recommendation. Add a job that runs cosign sign (keyless OIDC with GitLab's id_tokens works out of the box) or notation sign. Publish the signature next to the artifact and verify it on consume.
Source: GL-006 in the GitLab CI provider.
GL-007: SBOM not produced MEDIUM
Evidences: REB-3 L4: Generate SBOMs for artifacts produced.
How this is detected. Without an SBOM, downstream consumers can't audit the dependency set shipped in the artifact. Passes when CycloneDX / syft / anchore / spdx-sbom-generator / sbom-tool / Trivy-SBOM appears in the pipeline body.
Recommendation. Add an SBOM step, syft . -o cyclonedx-json, Trivy with --format cyclonedx, or GitLab's built-in CycloneDX dependency-scanning template. Attach the SBOM as a pipeline artifact.
Source: GL-007 in the GitLab CI provider.
GL-009: Image pinned to version tag rather than sha256 digest LOW
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. GL-001 fails floating tags at HIGH; GL-009 is the stricter tier. Even immutable-looking version tags (python:3.12.1) can be repointed by registry operators. Digest pins are the only tamper-evident form.
Recommendation. Resolve each image to its current digest (docker buildx imagetools inspect <ref> prints it) and replace the tag with @sha256:<digest>. Automate refreshes with Renovate.
Source: GL-009 in the GitLab CI provider.
GL-018: Package install from insecure source HIGH 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Detects package-manager invocations that use plain HTTP registries (--index-url http://, --registry=http://) or disable TLS verification (--trusted-host, --no-verify) in a pipeline. These patterns allow man-in-the-middle injection of malicious packages.
Recommendation. Use HTTPS registry URLs. Remove --trusted-host and --no-verify flags. Pin to a private registry with TLS.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: GL-018 in the GitLab CI provider.
GL-019: No vulnerability scanning step MEDIUM
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. Without a vulnerability scanning step, known-vulnerable dependencies ship to production undetected. The check recognises trivy, grype, snyk, npm audit, yarn audit, safety check, pip-audit, osv-scanner, and govulncheck.
Recommendation. Add a vulnerability scanning step, trivy, grype, snyk test, npm audit, pip-audit, or osv-scanner. Publish results so vulnerabilities surface before deployment.
Source: GL-019 in the GitLab CI provider.
GL-021: Package install without lockfile enforcement MEDIUM 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Detects package-manager install commands that do not enforce a lockfile or hash verification. Without lockfile enforcement the resolver pulls whatever version is currently latest, exactly the window a supply-chain attacker exploits.
Recommendation. Use lockfile-enforcing install commands: npm ci instead of npm install, pip install --require-hashes -r requirements.txt, yarn install --frozen-lockfile, bundle install --frozen, and go install tool@v1.2.3.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: GL-021 in the GitLab CI provider.
GL-022: Dependency update command bypasses lockfile pins MEDIUM 🔧 fix
Evidences: UPD-2 L3: Enable automated OSS updates (Dependabot / Renovate).
How this is detected. Detects pip install --upgrade, npm update, yarn upgrade, bundle update, cargo update, go get -u, and composer update. These commands bypass lockfile pins and pull whatever version is currently latest. Tooling upgrades (pip install --upgrade pip) are exempted.
Recommendation. Remove dependency-update commands from CI. Use lockfile-pinned install commands (npm ci, pip install -r requirements.txt) and update dependencies via a dedicated PR workflow (e.g. Dependabot, Renovate).
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Known false positives.
- Common build-tool bootstrapping idioms (
pip install --upgrade pip,pip install --upgrade setuptools wheel virtualenv) and security-tool installs (pip install --upgrade pip-audit / cyclonedx-bom / semgrep) are exempted by theDEP_UPDATE_REtooling allowlist. Other tooling-upgrade idioms not yet on the list can still trip the rule. Defaults to MEDIUM confidence so CI gates can require--min-confidence HIGHto ignore.
Source: GL-022 in the GitLab CI provider.
GL-024: No SLSA provenance attestation produced MEDIUM
Evidences: REB-4 L4: Digitally sign SBOMs produced (attested provenance).
How this is detected. cosign sign and cosign attest look similar but mean different things: the first binds identity to bytes; the second binds a structured claim (builder, source, inputs) to the artifact. SLSA Build L3 verifiers check the latter.
Recommendation. Add a job that runs cosign attest against a provenance.intoto.jsonl statement, or adopt a SLSA-aware builder (the SLSA project ships GitLab templates). Signing the artifact (GL-006) isn't enough for SLSA L3, the attestation describes how the build ran.
Source: GL-024 in the GitLab CI provider.
GL-025: Pipeline contains indicators of malicious activity CRITICAL
Evidences: SCA-3 L2: Scan OSS for malware.
How this is detected. Fires on concrete indicators (reverse shells, base64-decoded execution, miner binaries, Discord/Telegram webhooks, webhook.site callbacks, env | curl credential dumps, history -c audit erasure). Orthogonal to GL-003 (curl pipe) and GL-017 (Docker insecure flags). Those flag risky defaults; this flags evidence.
Recommendation. Treat as a potential compromise. Identify the MR that added the matching job(s), rotate any credentials the pipeline can reach, and audit recent runs for outbound traffic to the matched hosts. A legitimate red-team exercise should be time-bounded via .pipelinecheckignore with expires:.
Known false positives.
- Security-training repositories, CTF challenges, and red-team exercise pipelines legitimately contain reverse-shell strings or exfil domains as literals. Matches inside YAML keys / HCL attributes whose names contain
example,fixture,sample,demo, ortestare auto-suppressed; bare lines in a production pipeline still fire. - Defaults to LOW confidence. Filter with
--min-confidence MEDIUMto ignore all matches; the rule still surfaces the hit for teams that want to spot-check.
Source: GL-025 in the GitLab CI provider.
GL-027: Package install bypasses registry integrity (git / path / tarball source) MEDIUM
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Complements GL-021 (missing lockfile flag). Git URL installs without a commit pin, local-path installs, and direct tarball URLs all bypass the registry integrity controls the lockfile relies on, an attacker who can move a branch head, drop a sibling checkout, or change a served tarball can substitute code into the build.
Recommendation. Pin git dependencies to a commit SHA (pip install git+https://…/repo@<sha>, cargo install --git … --rev <sha>). Publish private packages to an internal registry instead of installing from a filesystem path or tarball URL.
Source: GL-027 in the GitLab CI provider.
GL-028: services: image not pinned HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. services: entries (top-level or per-job) can be either a string (redis:7) or a dict ({name: redis:7, alias: cache}). Both forms are normalized via image_ref-style extraction and evaluated with the same floating-tag regex GL-001 uses for image:.
Recommendation. Pin every services: entry the same way image: is pinned, prefer @sha256:<digest>, or at minimum a full immutable version tag (postgres:16.2-alpine). Avoid :latest and bare tags like :16.
Source: GL-028 in the GitLab CI provider.
GL-029: Manual deploy job defaults to allow_failure: true MEDIUM
Evidences: ENF-2 L2: Break the build when a violation is detected.
How this is detected. This is the most common GitLab deployment gotcha: a manual deploy job looks like a gate in the UI, but the pipeline reports success on the first run because the job is marked allow_failure by default. Downstream jobs (and the overall pipeline status) proceed as though the human approved.
Recommendation. Add allow_failure: false to every deploy-like when: manual job. GitLab defaults allow_failure to true for manual jobs, which makes the pipeline report success whether or not the operator clicks, exactly the opposite of the gate you meant to add.
Source: GL-029 in the GitLab CI provider.
GL-030: trigger: include: pulls child pipeline without pinned ref HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. GL-005 only audits top-level include:. Parent-child and multi-project pipelines that load YAML via the job-level trigger: include: slot slip through. Branch refs (main/master/develop/head) count as unpinned.
Recommendation. Pin trigger: include: project: entries with ref: set to a tag or commit SHA. Avoid trigger: include: remote: for untrusted URLs; mirror the content into a trusted project and pin it there.
Source: GL-030 in the GitLab CI provider.
HELM-001: Chart.yaml declares legacy apiVersion: v1 MEDIUM 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. apiVersion lives at the top of Chart.yaml. v1 is Helm 2's format and uses a sibling requirements.yaml for dependencies; v2 is Helm 3's format and inlines them in Chart.yaml alongside a Chart.lock for digest pinning. Without v2 there is no in-tree dependency manifest to lock, which is why HELM-002 only fires on v2 charts.
Recommendation. Bump Chart.yaml to apiVersion: v2 and migrate any sibling requirements.yaml entries into the dependencies: list inside Chart.yaml. Run helm dependency update to regenerate Chart.lock so HELM-002's per-dependency digest check has something to read. Helm 3 has been the default shipping channel since November 2019; the v1 format is kept for read-compat but blocks lockfile-based supply-chain controls.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: HELM-001 in the Helm provider.
HELM-002: Chart.lock missing per-dependency digests HIGH 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions), REB-3 L4: Generate SBOMs for artifacts produced.
How this is detected. Three failure shapes:
Chart.yamldeclares dependencies but noChart.lockexists at all.Chart.lockexists but itsdependencies:list is missing entries declared inChart.yaml(drift after an edit without re-runninghelm dependency update).Chart.locklists every dependency but one or more entries lack adigest:field (lock generated by an old Helm 3 version that didn't always populate it).
v1 charts (HELM-001) are skipped. They predate Chart.lock and use requirements.lock against a sibling requirements.yaml. Fix HELM-001 first.
Recommendation. After every change to dependencies: in Chart.yaml, re-run helm dependency update and commit the regenerated Chart.lock. The lock records the resolved version and a sha256:... digest that helm dependency build verifies on download, without it, a compromised chart repo can swap the tarball under the same version and helm install will happily use the substitute.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Known false positives.
- Charts with no dependencies (the
dependencies:key is absent or empty) pass automatically. There is nothing to lock.
Source: HELM-002 in the Helm provider.
HELM-003: Chart dependency declared on a non-HTTPS repository HIGH 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Walks Chart.yaml dependencies: (v2 charts only) and inspects each entry's repository: URL. Accepted schemes:
https://, chart-museum / OSS chart repos. The default for public Helm charts.oci://, registry-hosted charts. TLS is enforced by the registry, not the URL scheme; we still accept this shape because Helm 3.8+ pulls OCI charts over HTTPS unless explicitly configured otherwise.file://, in-repo dependency. No network surface.@alias, local alias for a previously registeredhelm repo addURL. The scheme of the original URL is the user's responsibility (and is captured in the chart consumer's~/.config/helm/repositories.yaml).
Recommendation. Switch each dependencies[].repository value to an https:// chart repo URL, an oci:// registry reference, or a file:// path for in-repo charts. Plaintext http:// (and other non-TLS schemes like git://) lets any on-path attacker substitute the dependency tarball during helm dependency build; Chart.lock's digest check (HELM-002) only catches that on the next update, not the compromised pull itself.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: HELM-003 in the Helm provider.
HELM-004: Chart dependency version is a range, not an exact pin MEDIUM
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. An exact pin is a string that contains only digits, dots, and at most a single leading v / trailing pre-release or build identifier (1.2.3, v1.2.3, 1.2.3-rc1, 1.2.3+build.5). Anything carrying ^ / ~ / > / < / * / x / X / || / a space (>=4 <5) is treated as a range. The bias is toward false positives, a chart maintainer can suppress per-rule via --ignore-file if they specifically want range semantics, but the default for production charts is a pin.
Recommendation. Replace each dependencies[].version constraint with the exact resolved version from Chart.lock. 17.0.0 instead of ^17.0.0, v1.2.3 instead of ~1.2. Range syntax (^, ~, >=, *, x) lets helm dependency update move every consumer of the chart to a newer dep on the next refresh, even when the lock file looked stable.
Source: HELM-004 in the Helm provider.
HELM-008: Chart.lock generated more than 90 days ago MEDIUM
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Reads Chart.lock's top-level generated: timestamp (an ISO-8601 string Helm writes when the lock was last regenerated) and compares against now. Fires when the delta is more than 90 days. Charts without Chart.lock are skipped. HELM-002 covers the missing-lock case directly. Charts whose generated: field is malformed or absent silently pass on this rule (HELM-002 covers the absent-lock case from a different angle).
Recommendation. Run helm dependency update against every dependency-carrying chart at least once per release cycle, and commit the regenerated Chart.lock. The lock pins versions and digests; the update cadence is what brings in CVE fixes and deprecation notices from the last quarter. CI can run the same command against main weekly to surface drift as a PR rather than letting the lock sit stale until the next release.
Known false positives.
- A chart that pins exact versions and never needs new dependencies (e.g. a chart packaging a single internal library that itself updates rarely) may legitimately have a stale Chart.lock. Suppress with
--ignore-filewhen this matches your situation.
Source: HELM-008 in the Helm provider.
HELM-009: Chart home / sources URL uses a non-HTTPS scheme LOW
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Walks Chart.yaml home: (single string) and sources: (list of strings). Fires on any value whose scheme is http://, ftp://, or other plaintext form. Empty / missing fields pass, the rule only evaluates URLs that are populated with the wrong scheme. HELM-003 covers the same risk for dependency-repo URLs.
Recommendation. Switch every home: URL and every entry in sources: to https://. Most chart-listing UIs display these as click-through links from a public chart registry; serving them over plaintext is a confused-deputy footgun for anyone evaluating the chart's provenance. http:// URLs against localhost are not exempted, production charts shouldn't ship references to a developer-local endpoint anyway.
Source: HELM-009 in the Helm provider.
JF-001: Shared library not pinned to a tag or commit HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. @main, @master, @develop, no-@ref, and any non-semver / non-SHA ref are floating. Whoever controls the upstream library can ship code into your build by pushing to that branch.
Recommendation. Pin every @Library('name@<ref>') to a release tag (e.g. @v1.4.2) or a 40-char commit SHA. Configure the library in Jenkins with 'Allow default version to be overridden' disabled so a pipeline can't escape the pin.
Source: JF-001 in the Jenkins provider.
JF-005: Deploy stage missing manual input approval MEDIUM
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation).
How this is detected. A stage named deploy / release / publish / promote should either use the declarative input { ... } directive or call input message: ... somewhere in its body. Without one, any push that triggers the pipeline ships to the target with no human review.
Recommendation. Add an input step to every deploy-like stage (e.g. input message: 'Promote to prod?', submitter: 'releasers'). Combine with a Jenkins folder-scoped permission so only release engineers see the prompt.
Source: JF-005 in the Jenkins provider.
JF-006: Artifacts not signed MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Passes when cosign / sigstore / slsa-* / notation-sign appears in executable Jenkinsfile text (comments are stripped before matching).
Recommendation. Add a sh 'cosign sign --yes …' step (the cosign-installer Jenkins plugin handles binary install). Publish the signature next to the artifact and verify it at deploy.
Source: JF-006 in the Jenkins provider.
JF-007: SBOM not produced MEDIUM
Evidences: REB-3 L4: Generate SBOMs for artifacts produced.
How this is detected. Passes when a direct SBOM tool token (CycloneDX, syft, anchore, spdx-sbom-generator, sbom-tool) appears in executable code, or when Trivy is paired with sbom / cyclonedx in the same file. Comments are stripped before matching.
Recommendation. Add a sh 'syft . -o cyclonedx-json > sbom.json' step (or Trivy with --format cyclonedx) and archive the result with archiveArtifacts.
Source: JF-007 in the Jenkins provider.
JF-009: Agent docker image not pinned to sha256 digest HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. agent { docker { image 'name:tag' } } is not digest-pinned, so a repointed registry tag silently swaps the executor under every subsequent build. Unlike the YAML providers, Jenkins has no separate tag-pinning check, so this one fires at HIGH regardless of whether the tag is floating or immutable.
Recommendation. Resolve each image to its current digest (docker buildx imagetools inspect <ref> prints it) and reference it via image '<repo>@sha256:<digest>'. Automate refreshes with Renovate.
Source: JF-009 in the Jenkins provider.
JF-018: Package install from insecure source HIGH 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Detects package-manager invocations that use plain HTTP registries (--index-url http://, --registry=http://) or disable TLS verification (--trusted-host, --no-verify) in a Jenkinsfile. These patterns allow man-in-the-middle injection of malicious packages.
Recommendation. Use HTTPS registry URLs. Remove --trusted-host and --no-verify flags. Pin to a private registry with TLS.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: JF-018 in the Jenkins provider.
JF-020: No vulnerability scanning step MEDIUM
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. Without a vulnerability scanning step, known-vulnerable dependencies ship to production undetected. The check recognises trivy, grype, snyk, npm audit, yarn audit, safety check, pip-audit, osv-scanner, and govulncheck. Comments are stripped before matching.
Recommendation. Add a vulnerability scanning step, trivy, grype, snyk test, npm audit, pip-audit, or osv-scanner. Publish results so vulnerabilities surface before deployment.
Source: JF-020 in the Jenkins provider.
JF-021: Package install without lockfile enforcement MEDIUM 🔧 fix
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Detects package-manager install commands that do not enforce a lockfile or hash verification. Without lockfile enforcement the resolver pulls whatever version is currently latest, exactly the window a supply-chain attacker exploits.
Recommendation. Use lockfile-enforcing install commands: npm ci instead of npm install, pip install --require-hashes -r requirements.txt, yarn install --frozen-lockfile, bundle install --frozen, and go install tool@v1.2.3.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: JF-021 in the Jenkins provider.
JF-022: Dependency update command bypasses lockfile pins MEDIUM 🔧 fix
Evidences: UPD-2 L3: Enable automated OSS updates (Dependabot / Renovate).
How this is detected. Detects pip install --upgrade, npm update, yarn upgrade, bundle update, cargo update, go get -u, and composer update. These commands bypass lockfile pins and pull whatever version is currently latest. Tooling upgrades (pip install --upgrade pip) are exempted.
Recommendation. Remove dependency-update commands from CI. Use lockfile-pinned install commands (npm ci, pip install -r requirements.txt) and update dependencies via a dedicated PR pipeline (e.g. Dependabot, Renovate).
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Known false positives.
- Common build-tool bootstrapping idioms (
pip install --upgrade pip,pip install --upgrade setuptools wheel virtualenv) and security-tool installs (pip install --upgrade pip-audit / cyclonedx-bom / semgrep) are exempted by theDEP_UPDATE_REtooling allowlist. Other tooling-upgrade idioms not yet on the list can still trip the rule. Defaults to MEDIUM confidence so CI gates can require--min-confidence HIGHto ignore.
Source: JF-022 in the Jenkins provider.
JF-024: input approval step missing submitter restriction MEDIUM
Evidences: ENF-1 L2: Enforce security policy of OSS usage (block on violation).
How this is detected. JF-005 already flags deploy stages with no input step. This rule catches the subtler case: the gate exists, but it doesn't actually restrict approvers. submitter accepts a comma-separated list of Jenkins usernames and group names; scope it to the smallest release-eligible pool.
Recommendation. Add a submitter: 'releasers,sre' (or a single role) argument to every input step in a deploy-like stage. Without it, any user with the Jenkins job Build permission can approve a production promotion, the approval gate becomes advisory.
Source: JF-024 in the Jenkins provider.
JF-028: No SLSA provenance attestation produced MEDIUM
Evidences: REB-4 L4: Digitally sign SBOMs produced (attested provenance).
How this is detected. cosign sign signs the artifact bytes. cosign attest signs an in-toto statement describing how the build ran, builder, source commit, input parameters. SLSA L3 verifiers check the latter so consumers can enforce policy on where and how artifacts were produced.
Recommendation. Add a sh 'cosign attest --predicate=provenance.intoto.jsonl …' step after the build, or integrate the TestifySec witness run attestor. JF-006 covers signing; this rule covers the build-provenance statement SLSA Build L3 requires.
Source: JF-028 in the Jenkins provider.
JF-029: Jenkinsfile contains indicators of malicious activity CRITICAL
Evidences: SCA-3 L2: Scan OSS for malware.
How this is detected. Distinct from JF-016 (curl pipe) and JF-019 (Groovy sandbox escape). Those flag risky defaults; this flags concrete evidence, reverse shells, base64-decoded execution, miner binaries, exfil channels, credential-dump pipes, shell-history erasure. Runs on the comment-stripped Groovy text so // cosign verify … // webhook.site in a legitimate annotation doesn't false-positive.
Recommendation. Treat as a potential compromise. Identify the commit that introduced the matching stage(s), rotate Jenkins credentials the job can reach, review controller/agent audit logs for outbound traffic to the matched hosts, and re-image the agent pool if the compromise may have persisted.
Known false positives.
- Security-training repositories, CTF challenges, and red-team exercise pipelines legitimately contain reverse-shell strings or exfil domains as literals. Matches inside YAML keys / HCL attributes whose names contain
example,fixture,sample,demo, ortestare auto-suppressed; bare lines in a production pipeline still fire. - Defaults to LOW confidence. Filter with
--min-confidence MEDIUMto ignore all matches; the rule still surfaces the hit for teams that want to spot-check.
Source: JF-029 in the Jenkins provider.
JF-031: Package install bypasses registry integrity (git / path / tarball source) MEDIUM
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Complements JF-021 (missing lockfile flag). Git URL installs without a commit pin, local-path installs, and direct tarball URLs bypass the registry integrity controls the lockfile relies on.
Recommendation. Pin git dependencies to a commit SHA. Publish private packages to an internal registry (Artifactory, Nexus) instead of installing from a filesystem path or tarball URL.
Source: JF-031 in the Jenkins provider.
LMB-001: Lambda function has no code-signing config HIGH
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Lambda code-signing config + a Signer profile (SIGN-001) validates that an uploaded zip was signed by a known profile before it's allowed to run. Without one, anyone who reaches lambda:UpdateFunctionCode, a CI/CD role compromise, a misattached IAM policy, can replace the function's code with no chain-of-custody check.
Recommendation. Create an AWS Signer profile, reference it from an aws_lambda_code_signing_config with untrusted_artifact_on_deployment = Enforce and attach that config to the function. Without one, the Lambda runtime will execute any code that a principal with lambda:UpdateFunctionCode uploads.
Source: LMB-001 in the AWS provider.
SIGN-001: No AWS Signer profile defined for Lambda deploys MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. AWS Signer profiles are the upstream of LMB-001's code-signing config. Without a profile defined, no function in the account can enforce code-signing, LMB-001's recommendation has nothing to point at. The profile is the foundation; the per-function code-signing config attaches it.
Recommendation. Create an AWS Signer profile with platform AWSLambda-SHA384-ECDSA and reference it from every Lambda code-signing config used by the pipeline. Without a profile, LMB-001 remediation isn't possible and release artifacts can't be signed at build time.
Source: SIGN-001 in the AWS provider.
SIGN-002: AWS Signer profile is revoked or inactive HIGH
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. A revoked or canceled Signer profile invalidates every signature it ever produced. Lambda functions configured to enforce code-signing fail to deploy until the profile is replaced (or, if UntrustedArtifactOnDeployment = Warn, deploy with a CloudWatch warning the operator rarely reads).
Recommendation. Rotate the signing profile: create a replacement and update every code-signing config that references the revoked profile. A revoked or canceled profile invalidates every signature it produced, lambdas relying on it will fail verification.
Source: SIGN-002 in the AWS provider.
TKN-001: Tekton step image not pinned to a digest HIGH
Evidences: UPD-1 L1: Update vulnerable OSS manually (pin + track versions).
How this is detected. Applies to Task and ClusterTask kinds. The image must contain @sha256: followed by a 64-char hex digest. Any tag-only reference, including :latest, fails.
Recommendation. Pin every step image to a content-addressable digest (gcr.io/tekton-releases/git-init@sha256:<digest>). Tag-only references (alpine:3.18) and rolling tags (alpine:latest) let a compromised registry update redirect the step at the next pull, with no audit trail in the Task manifest.
Source: TKN-001 in the Tekton provider.
TKN-008: Tekton step script pipes remote install or disables TLS HIGH 🔧 fix
Evidences: ING-1 L1: Use package managers trusted by your organization.
How this is detected. Uses the cross-provider CURL_PIPE_RE and TLS_BYPASS_RE regexes so detection is consistent with the GHA / GitLab / CircleCI / Cloud Build providers.
Recommendation. Replace curl ... | sh with a download-then-verify-then-execute pattern. Drop TLS-bypass flags (curl -k, git config http.sslverify false); install the missing CA into the step image instead. Both forms let an attacker controlling DNS / a transparent proxy substitute the script the step runs.
Autofix. pipeline_check --fix will patch this finding automatically. Review the diff before committing; the fixer applies the conservative remediation pattern (e.g. swap a floating tag for the digest it currently resolves to), not the most aggressive one.
Source: TKN-008 in the Tekton provider.
TKN-009: Artifacts not signed (no cosign/sigstore step) MEDIUM
Evidences: REB-2 L4: Digitally sign rebuilt / produced OSS artifacts.
How this is detected. Detection mirrors GHA-006 / BK-009 / CC-006, the shared signing-token catalog (cosign, sigstore, slsa-github-generator, slsa-framework, notation-sign) is searched across every string in the Task / Pipeline document. The rule only fires on artifact-producing Tasks (those that invoke docker build / docker push / buildah / kaniko / helm upgrade / aws s3 sync / etc.) so lint-only Tasks don't trip it.
Recommendation. Add a signing step to the Task, either a dedicated cosign sign step after the build, or use the official cosign Tekton catalog Task as a referenced step. The Task should sign by digest (cosign sign --yes <repo>@sha256:<digest>) so a re-pushed tag can't bypass the signature.
Source: TKN-009 in the Tekton provider.
TKN-010: No SBOM generated for build artifacts MEDIUM
Evidences: REB-3 L4: Generate SBOMs for artifacts produced.
How this is detected. An SBOM (CycloneDX or SPDX) records every component baked into the build. Without one, post-incident triage can't answer did this CVE ship? for a given artifact. Detection uses the shared SBOM-token catalog: syft, cyclonedx, cdxgen, spdx-tools, microsoft/sbom-tool. Fires only on artifact-producing Tasks.
Recommendation. Add an SBOM-generation step. syft <artifact> -o cyclonedx-json > $(workspaces.output.path)/sbom.json runs in the official syft Tekton catalog Task. cyclonedx-cli and cdxgen are alternatives. Publish the SBOM as a Workspace result so downstream Tasks can consume it.
Source: TKN-010 in the Tekton provider.
TKN-011: No SLSA provenance attestation produced MEDIUM
Evidences: REB-4 L4: Digitally sign SBOMs produced (attested provenance).
How this is detected. Provenance generation is distinct from signing. A signed artifact proves who published it; a provenance attestation proves where / how it was built. Tekton Chains is the Tekton-native answer, once enabled on the cluster, every TaskRun's outputs are signed and attested without per-Task wiring. Detection uses the shared provenance-token catalog (slsa-framework, cosign attest, in-toto, attest-build-provenance, witness run). Tasks produced by tekton-chains pass on the cosign attest match.
Recommendation. After the build step, run cosign attest --predicate slsa.json --type slsaprovenance <ref> (or use the tekton-chains controller, which signs and attests every TaskRun automatically when configured). Publish the attestation alongside the artifact so consumers can verify how it was built, not just who signed it.
Source: TKN-011 in the Tekton provider.
TKN-012: No vulnerability scanning step MEDIUM
Evidences: SCA-1 L1: Scan OSS for known vulnerabilities.
How this is detected. Vulnerability scanning sits at a different layer from signing and SBOM. It answers does this artifact ship a known CVE? rather than can we verify what it is?. Detection uses the shared vuln-scan-token catalog: trivy, grype, snyk, npm-audit, pip-audit, osv-scanner, govulncheck, anchore, codeql-action, semgrep, bandit, checkov, tfsec, dependency-check. Walks every Task / Pipeline / *Run document; passes if any document includes a scanner reference.
Recommendation. Add a vulnerability scanner step. trivy fs $(workspaces.src.path) for source / filesystem; trivy image <ref> for container images. The official Tekton catalog ships trivy-scanner and grype-scanner Tasks if you'd rather reference one. Fail the step on findings above a chosen severity so a regression blocks the merge instead of shipping.
Source: TKN-012 in the Tekton provider.
This page is generated. Edit pipeline_check/core/standards/data/s2c2f.py (mappings) or scripts/gen_standards_docs.py (intro / per-control prose) and run python scripts/gen_standards_docs.py s2c2f.