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: 394
- Of those, autofixable with
--fix: 43
Severity levels (CRITICAL / HIGH / MEDIUM / LOW / INFO) follow the same scale across every provider and standard. See How to read severity on the standards overview for the definitions.
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 | 87 | 1C · 63H · 21M · 2L |
ING-3 |
L1: Have the capability to deny-list specific vulnerable / malicious OSS | 29 | 10C · 15H · 4M |
SCA-1 |
L1: Scan OSS for known vulnerabilities | 18 | 3H · 15M |
SCA-3 |
L2: Scan OSS for malware | 36 | 18C · 12H · 6M |
UPD-1 |
L1: Update vulnerable OSS manually (pin + track versions) | 87 | 47H · 33M · 7L |
UPD-2 |
L3: Enable automated OSS updates (Dependabot / Renovate) | 6 | 6M |
ENF-1 |
L2: Enforce security policy of OSS usage (block on violation) | 71 | 4C · 31H · 33M · 2L · 1I |
ENF-2 |
L2: Break the build when a violation is detected | 26 | 5H · 20M · 1L |
REB-2 |
L4: Digitally sign rebuilt / produced OSS artifacts | 25 | 3H · 20M · 2L |
REB-3 |
L4: Generate SBOMs for artifacts produced | 27 | 3H · 17M · 7L |
REB-4 |
L4: Digitally sign SBOMs produced (attested provenance) | 16 | 4H · 12M |
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 87 checks across 24 providers (AWS, Argo Workflows, Azure Cloud, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, Composer, Dockerfile, Drone CI, GCP, GitHub Actions, GitLab CI, Harness CI/CD, Helm, Jenkins, Modelfile, NuGet, PyPI, RubyGems, Tekton, maven, npm).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-018 |
Package install from insecure source | HIGH | Azure DevOps | 🔧 fix |
ADO-023 |
TLS / certificate verification bypass | 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 |
AZAPP-001 |
App Service does not enforce HTTPS | HIGH | Azure Cloud | |
AZAPP-002 |
App Service minimum TLS version below 1.2 | HIGH | Azure Cloud | |
AZST-002 |
Storage account allows non-HTTPS traffic | HIGH | Azure Cloud | |
AZST-004 |
Storage account minimum TLS version below 1.2 | HIGH | Azure Cloud | |
BB-014 |
Package install from insecure source | HIGH | Bitbucket | 🔧 fix |
BB-023 |
TLS / certificate verification bypass | 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 | |
COMPOSER-003 |
composer.json repository declared over plain HTTP | HIGH | Composer | |
COMPOSER-004 |
composer.json repository URL embeds plaintext credentials | HIGH | Composer | |
COMPOSER-005 |
composer.json minimum-stability accepts unstable releases | MEDIUM | Composer | |
COMPOSER-009 |
auth.json committed alongside composer.json with literal credentials | HIGH | Composer | |
COMPOSER-010 |
composer.json config.secure-http: false disables HTTPS enforcement | MEDIUM | Composer | |
COMPOSER-011 |
composer.json repository re-points a package to an external VCS source | HIGH | Composer | |
COMPOSER-012 |
composer.json disables Packagist or marks a custom repo canonical | HIGH | Composer | |
COMPOSER-013 |
composer.json config.disable-tls turns off certificate verification | HIGH | Composer | |
COMPOSER-014 |
composer.json minimum-stability lowered without prefer-stable | MEDIUM | Composer | |
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 | |
DF-021 |
RUN pip install bypasses TLS or uses an HTTP index | HIGH | Dockerfile | |
DF-022 |
RUN uses npm install instead of npm ci | MEDIUM | Dockerfile | |
DF-024 |
RUN npm/yarn/pnpm install runs lifecycle scripts | HIGH | Dockerfile | |
DF-026 |
ENV disables Node.js TLS certificate verification | HIGH | Dockerfile | |
DF-027 |
ENV disables Python HTTPS certificate verification | HIGH | Dockerfile | |
DF-028 |
ENV disables Git TLS certificate verification | HIGH | Dockerfile | |
DF-029 |
ENV neuters Python requests CA bundle | HIGH | Dockerfile | |
DF-031 |
COPY --from external image not pinned to sha256 digest | HIGH | Dockerfile | |
DR-006 |
TLS verification disabled in step commands | HIGH | Drone CI | 🔧 fix |
ECR-006 |
ECR pull-through cache rule uses an untrusted upstream | HIGH | AWS | |
GCB-011 |
TLS / certificate verification bypass | HIGH | Cloud Build | 🔧 fix |
GCSQL-003 |
Cloud SQL instance does not require SSL connections | HIGH | GCP | |
GEM-003 |
Gemfile source declared over plain HTTP | HIGH | RubyGems | |
GEM-004 |
Gemfile source URL embeds plaintext credentials | HIGH | RubyGems | |
GEM-007 |
Gemfile declares multiple top-level sources without scoping | MEDIUM | RubyGems | |
GEM-009 |
.bundle/config committed with embedded credentials | HIGH | RubyGems | |
GHA-016 |
Remote script piped to shell interpreter | HIGH | GitHub Actions | 🔧 fix |
GHA-017 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | GitHub Actions | 🔧 fix |
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-023 |
TLS / certificate verification bypass | HIGH | GitLab CI | 🔧 fix |
GL-027 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | GitLab CI | |
HARNESS-006 |
TLS verification disabled in step commands | HIGH | Harness CI/CD | 🔧 fix |
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-023 |
TLS / certificate verification bypass | HIGH | Jenkins | 🔧 fix |
JF-031 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | Jenkins | |
JF-035 |
httpRequest step disables SSL verification | HIGH | Jenkins | |
MODEL-001 |
Base model pulled without a pinned reference | MEDIUM | Modelfile | |
MODEL-002 |
Base model pulled from a third-party hub | MEDIUM | Modelfile | |
MODEL-003 |
Base model loaded from a local unverified weights blob | LOW | Modelfile | |
MODEL-004 |
LoRA adapter applied from a remote source | MEDIUM | Modelfile | |
MODEL-005 |
Vendored model config declares custom loader code (auto_map) | MEDIUM | Modelfile | |
MVN-003 |
pom.xml declares a plaintext-HTTP Maven repository | HIGH | maven | |
MVN-007 |
settings.xml mirror routes external traffic through one repo | MEDIUM | maven | |
NPM-003 |
package-lock.json entry resolves from a non-registry source | HIGH | npm | |
NPM-004 |
package.json declares an install-time lifecycle script | HIGH | npm | |
NPM-007 |
.npmrc does not disable install-time lifecycle scripts | HIGH | npm | |
NUGET-004 |
HTTP-only NuGet package source | HIGH | NuGet | |
NUGET-007 |
Multiple NuGet sources without packageSourceMapping | HIGH | NuGet | |
NUGET-010 |
NuGet.config stores a feed credential in plaintext | HIGH | NuGet | |
NUGET-011 |
packageSourceMapping pattern is a global wildcard | HIGH | NuGet | |
NUGET-012 |
NuGet.config does not enforce signatureValidationMode = require | HIGH | NuGet | |
NUGET-013 |
dotnet-tools.json entry lacks a version pin | HIGH | NuGet | |
NUGET-014 |
NuGet.config source URL embeds plaintext credentials | HIGH | NuGet | |
NUGET-015 |
PackageReference VersionOverride defeats Central Package Management | MEDIUM | NuGet | |
NUGET-016 |
Private feed without |
HIGH | NuGet | |
NUGET-017 |
Public gallery active alongside a private feed, not disabled | HIGH | NuGet | |
NUGET-018 |
Project runs build-time MSBuild logic at restore/build | HIGH | NuGet | |
NUGET-019 |
signatureValidationMode=require with no trusted signers | HIGH | NuGet | |
PYPI-003 |
requirements.txt uses an HTTP index or disables TLS verification | HIGH | PyPI | |
PYPI-005 |
requirements.txt declares --extra-index-url (dependency-confusion surface) | HIGH | PyPI | |
PYPI-016 |
requirements.txt repoints the primary index at a non-PyPI host | HIGH | PyPI | |
PYPI-017 |
requirements.txt uses a remote --find-links source | MEDIUM | PyPI | |
PYPI-018 |
requirements.txt forces source builds via --no-binary | MEDIUM | PyPI | |
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 29 checks across 9 providers (AWS, Composer, GitHub Actions, Helm, NuGet, PyPI, RubyGems, maven, npm).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
CA-002 |
CodeArtifact repository has a public external connection | HIGH | AWS | |
COMPOSER-007 |
composer.json requires a known-compromised package version | HIGH | Composer | |
COMPOSER-008 |
composer.json allow-plugins permits any plugin to execute | HIGH | Composer | |
ECR-006 |
ECR pull-through cache rule uses an untrusted upstream | HIGH | AWS | |
GEM-006 |
Gemfile requires a known-compromised gem version | HIGH | RubyGems | |
GHA-040 |
Action reference matches a known-compromised SHA or tag | CRITICAL | GitHub Actions | |
GHA-041 |
Action upstream repo has a single contributor | MEDIUM | GitHub Actions | |
GHA-042 |
Action upstream repo is newly created | MEDIUM | GitHub Actions | |
GHA-043 |
Low-star action runs with sensitive permissions | HIGH | GitHub Actions | |
GHA-047 |
Action ref resolves to a recently committed tag or SHA | MEDIUM | GitHub Actions | |
GHA-056 |
Workflow body contains a known supply-chain worm indicator | CRITICAL | GitHub Actions | |
HELM-016 |
values.yaml ships a default secret or credential | HIGH | Helm | |
MVN-006 |
pom.xml pins a known-compromised Maven Central artifact version | CRITICAL | maven | |
MVN-008 |
Direct dependency was published within the cooldown window | HIGH | maven | |
MVN-009 |
Maven artifact has a known OSV advisory | CRITICAL | maven | |
MVN-010 |
settings.xml |
HIGH | maven | |
MVN-011 |
Maven repository URL embeds plaintext credentials | HIGH | maven | |
MVN-012 |
pom.xml build plugin uses a floating version | HIGH | maven | |
MVN-013 |
pom.xml build extension uses a floating version | HIGH | maven | |
MVN-014 |
Maven Wrapper distributionUrl lacks distributionSha256Sum | MEDIUM | maven | |
NPM-006 |
package-lock.json pins a known-compromised package version | CRITICAL | npm | |
NPM-008 |
Direct dependency was published within the cooldown window | HIGH | npm | |
NPM-010 |
npm package has a known OSV advisory | CRITICAL | npm | |
NUGET-005 |
Known-compromised NuGet package version | CRITICAL | NuGet | |
NUGET-008 |
NuGet package published within the cooldown window | HIGH | NuGet | |
NUGET-009 |
NuGet package has a known OSV advisory | CRITICAL | NuGet | |
PYPI-006 |
requirements.txt pins a known-compromised PyPI package version | CRITICAL | PyPI | |
PYPI-008 |
Direct dependency was published within the cooldown window | HIGH | PyPI | |
PYPI-009 |
PyPI package has a known OSV advisory | CRITICAL | PyPI |
SCA-1: L1: Scan OSS for known vulnerabilities
Evidenced by 18 checks across 15 providers (AWS, Argo Workflows, Azure Cloud, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, Drone CI, GCP, GitHub Actions, GitLab CI, Harness CI/CD, Jenkins, Tekton).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ACR-004 |
Container registry Defender scanning not enabled | HIGH | Azure Cloud | |
ADO-020 |
No vulnerability scanning step | MEDIUM | Azure DevOps | |
ARGO-012 |
No vulnerability scanning step | MEDIUM | Argo Workflows | |
AZSQL-005 |
SQL Server advanced threat protection not enabled | MEDIUM | Azure Cloud | |
AZVM-004 |
Virtual machine automatic OS patching not enabled | MEDIUM | Azure Cloud | |
BB-015 |
No vulnerability scanning step | MEDIUM | Bitbucket | |
BK-012 |
No vulnerability scanning step | MEDIUM | Buildkite | |
CC-020 |
No vulnerability scanning step | MEDIUM | CircleCI | |
DR-022 |
No vulnerability-scan step (trivy / grype / snyk) | MEDIUM | Drone CI | |
ECR-001 |
Image scanning on push not enabled | HIGH | AWS | |
ECR-007 |
Inspector v2 enhanced scanning disabled for ECR | MEDIUM | AWS | |
GAR-001 |
Artifact Registry repository has no vulnerability scanning | HIGH | GCP | |
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 | |
HARNESS-018 |
No vulnerability-scan step (trivy / grype / snyk) | MEDIUM | Harness CI/CD | |
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 36 checks across 14 providers (AWS, Azure DevOps, Bitbucket, CircleCI, Composer, GitHub Actions, GitLab CI, Helm, Jenkins, NuGet, PyPI, RubyGems, maven, npm).
| 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 | |
BB-030 |
npm install without registry-signature verification step | MEDIUM | Bitbucket | |
BB-031 |
pip install without --require-hashes verification |
MEDIUM | Bitbucket | |
CB-011 |
CodeBuild buildspec contains indicators of malicious activity | CRITICAL | AWS | |
CC-026 |
Config contains indicators of malicious activity | CRITICAL | CircleCI | |
COMPOSER-007 |
composer.json requires a known-compromised package version | HIGH | Composer | |
COMPOSER-008 |
composer.json allow-plugins permits any plugin to execute | HIGH | Composer | |
GEM-006 |
Gemfile requires a known-compromised gem version | HIGH | RubyGems | |
GHA-027 |
Workflow contains indicators of malicious activity | CRITICAL | GitHub Actions | |
GHA-040 |
Action reference matches a known-compromised SHA or tag | CRITICAL | GitHub Actions | |
GHA-056 |
Workflow body contains a known supply-chain worm indicator | CRITICAL | GitHub Actions | |
GHA-057 |
Secret-scanner output sent to network egress | CRITICAL | GitHub Actions | |
GHA-058 |
Agentic CLI invoked with permission-bypass flags | HIGH | GitHub Actions | |
GHA-059 |
npm install without registry-signature verification step | MEDIUM | GitHub Actions | |
GHA-060 |
pip install without --require-hashes verification |
MEDIUM | GitHub Actions | |
GL-025 |
Pipeline contains indicators of malicious activity | CRITICAL | GitLab CI | |
GL-034 |
npm install without registry-signature verification step | MEDIUM | GitLab CI | |
GL-035 |
pip install without --require-hashes verification |
MEDIUM | GitLab CI | |
HELM-015 |
OCI chart dependency pinned only by a mutable tag | HIGH | Helm | |
HELM-017 |
Template renders an untrusted value through tpl | HIGH | Helm | |
JF-029 |
Jenkinsfile contains indicators of malicious activity | CRITICAL | Jenkins | |
MVN-006 |
pom.xml pins a known-compromised Maven Central artifact version | CRITICAL | maven | |
MVN-008 |
Direct dependency was published within the cooldown window | HIGH | maven | |
MVN-009 |
Maven artifact has a known OSV advisory | CRITICAL | maven | |
MVN-012 |
pom.xml build plugin uses a floating version | HIGH | maven | |
MVN-013 |
pom.xml build extension uses a floating version | HIGH | maven | |
NPM-006 |
package-lock.json pins a known-compromised package version | CRITICAL | npm | |
NPM-008 |
Direct dependency was published within the cooldown window | HIGH | npm | |
NPM-010 |
npm package has a known OSV advisory | CRITICAL | npm | |
NUGET-005 |
Known-compromised NuGet package version | CRITICAL | NuGet | |
NUGET-008 |
NuGet package published within the cooldown window | HIGH | NuGet | |
NUGET-009 |
NuGet package has a known OSV advisory | CRITICAL | NuGet | |
PYPI-006 |
requirements.txt pins a known-compromised PyPI package version | CRITICAL | PyPI | |
PYPI-008 |
Direct dependency was published within the cooldown window | HIGH | PyPI | |
PYPI-009 |
PyPI package has a known OSV advisory | CRITICAL | PyPI |
UPD-1: L1: Update vulnerable OSS manually (pin + track versions)
Evidenced by 87 checks across 25 providers (AWS, Argo Workflows, Azure Cloud, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, Composer, Dockerfile, Drone CI, GCP, GitHub Actions, GitLab CI, Harness CI/CD, Helm, Jenkins, Modelfile, NuGet, OCI manifest, PyPI, RubyGems, Tekton, maven, npm).
| 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 | |
AKV-004 |
Key Vault key has no expiration date | MEDIUM | Azure Cloud | |
AKV-005 |
Key Vault secret has no expiration date | MEDIUM | Azure Cloud | |
ARGO-001 |
Argo template container image not pinned to a digest | HIGH | Argo Workflows | |
AZST-005 |
Storage account blob lifecycle policy should be reviewed | LOW | Azure Cloud | |
AZST-006 |
Storage account access keys not rotated within 90 days | HIGH | Azure Cloud | |
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 |
BB-029 |
image: (step or service) not pinned by sha256 digest | HIGH | Bitbucket | |
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 | |
COMPOSER-001 |
composer.json present without a sibling composer.lock | HIGH | Composer | |
COMPOSER-002 |
composer.json require uses a floating version constraint | MEDIUM | Composer | |
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 | |
DF-022 |
RUN uses npm install instead of npm ci | MEDIUM | Dockerfile | |
DF-031 |
COPY --from external image not pinned to sha256 digest | HIGH | Dockerfile | |
DR-001 |
Step image not pinned to a digest | HIGH | Drone CI | |
DR-005 |
Plugin step uses a floating image tag | HIGH | Drone CI | |
DR-008 |
Step uses pull: never (skips registry verification) |
MEDIUM | Drone CI | |
ECR-002 |
Image tags are mutable | HIGH | AWS | |
ENTRA-002 |
App registration credential valid beyond 180 days | HIGH | Azure Cloud | |
ENTRA-003 |
Service principal uses password credential | HIGH | Azure Cloud | |
GAR-003 |
Artifact Registry has no cleanup policy | MEDIUM | GCP | |
GCB-001 |
Cloud Build step image not pinned by digest | HIGH | Cloud Build | 🔧 fix |
GCIAM-002 |
Service account has user-managed key | HIGH | GCP | |
GCIAM-006 |
Service account key older than 90 days | HIGH | GCP | |
GCKMS-001 |
KMS key rotation period exceeds 365 days | MEDIUM | GCP | |
GCS-003 |
Bucket versioning not enabled | MEDIUM | GCP | |
GEM-001 |
Gemfile present without a sibling Gemfile.lock | HIGH | RubyGems | |
GEM-002 |
Gemfile gem entry uses a floating version constraint | MEDIUM | RubyGems | |
GEM-005 |
Gemfile gem with git: / github: source missing a ref SHA pin | HIGH | RubyGems | |
GHA-001 |
Action not pinned to commit SHA | HIGH | GitHub Actions | 🔧 fix |
GHA-021 |
Package install without lockfile enforcement | MEDIUM | GitHub Actions | 🔧 fix |
GHA-023 |
TLS / certificate verification bypass | HIGH | GitHub Actions | 🔧 fix |
GHA-025 |
Reusable workflow not pinned to commit SHA | HIGH | GitHub Actions | |
GHA-051 |
services / container image is not pinned by digest | 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 | |
GL-042 |
include: component pulls a CI/CD component without a pinned version | HIGH | GitLab CI | |
HARNESS-001 |
Step image not pinned to a digest | HIGH | Harness CI/CD | |
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 |
MODEL-001 |
Base model pulled without a pinned reference | MEDIUM | Modelfile | |
MODEL-002 |
Base model pulled from a third-party hub | MEDIUM | Modelfile | |
MODEL-003 |
Base model loaded from a local unverified weights blob | LOW | Modelfile | |
MODEL-004 |
LoRA adapter applied from a remote source | MEDIUM | Modelfile | |
MODEL-005 |
Vendored model config declares custom loader code (auto_map) | MEDIUM | Modelfile | |
MVN-001 |
pom.xml dependency uses a floating version range | MEDIUM | maven | |
MVN-002 |
pom.xml depends on a mutable SNAPSHOT version | MEDIUM | maven | |
MVN-004 |
pom.xml dependency omits an explicit <version> |
MEDIUM | maven | |
MVN-005 |
Maven repository accepts artifacts without strict checksum gating | MEDIUM | maven | |
NPM-001 |
package.json dependency uses a floating version range | MEDIUM | npm | |
NPM-002 |
package-lock.json entry missing integrity hash | HIGH | npm | |
NPM-005 |
package.json git dependency uses a mutable ref | HIGH | npm | |
NUGET-001 |
Floating NuGet version range | MEDIUM | NuGet | |
NUGET-002 |
Wildcard prerelease NuGet version | MEDIUM | NuGet | |
NUGET-003 |
PackageReference missing explicit version | MEDIUM | NuGet | |
NUGET-006 |
No NuGet lock file for reproducible restores | MEDIUM | NuGet | |
OCI-007 |
Image manifest uses legacy schemaVersion 1 (no content addressing) | HIGH | OCI manifest | |
OCI-008 |
Manifest references digest using unsupported hash algorithm | HIGH | OCI manifest | |
PYPI-001 |
requirements.txt entry missing an exact version pin | MEDIUM | PyPI | |
PYPI-002 |
requirements.txt missing hash pinning (--require-hashes / --hash=) | HIGH | PyPI | |
PYPI-004 |
requirements.txt VCS dependency uses a mutable ref | HIGH | PyPI | |
PYPI-015 |
requirements.txt installs from a direct artifact URL | HIGH | PyPI | |
TKN-001 |
Tekton step image not pinned to a digest | HIGH | Tekton | |
TKN-016 |
Remote resolver taskRef / pipelineRef not pinned to an immutable revision | 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 71 checks across 11 providers (AWS, Azure Cloud, Azure DevOps, Bitbucket, Buildkite, CircleCI, GCP, GitHub Actions, GitLab CI, Harness CI/CD, Jenkins).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ACR-001 |
Container registry admin user enabled | HIGH | Azure Cloud | |
ACR-002 |
Container registry allows public network access | HIGH | Azure Cloud | |
ACR-005 |
Container registry tag immutability (verify per-repository locking) | INFO | Azure Cloud | |
ADO-004 |
Deployment job missing environment binding | MEDIUM | Azure DevOps | |
ADO-038 |
Agentic CLI output lands without human review | HIGH | Azure DevOps | |
AKV-001 |
Key Vault soft delete not enabled | HIGH | Azure Cloud | |
AKV-002 |
Key Vault purge protection not enabled | HIGH | Azure Cloud | |
AKV-003 |
Key Vault allows access from all networks | MEDIUM | Azure Cloud | |
AKV-006 |
Key Vault uses vault access policies instead of RBAC | MEDIUM | Azure Cloud | |
AZAPP-003 |
App Service does not use a managed identity | MEDIUM | Azure Cloud | |
AZAPP-004 |
App Service has remote debugging enabled | HIGH | Azure Cloud | |
AZAPP-005 |
App Service FTP access not disabled | MEDIUM | Azure Cloud | |
AZNW-001 |
NSG allows inbound SSH or RDP from the internet | CRITICAL | Azure Cloud | |
AZNW-003 |
Application Gateway does not have WAF enabled | HIGH | Azure Cloud | |
AZNW-004 |
NSG has no explicit deny-all inbound rule | MEDIUM | Azure Cloud | |
AZNW-005 |
Public IP address associated with a VM NIC | HIGH | Azure Cloud | |
AZSQL-003 |
SQL Server allows public network access | HIGH | Azure Cloud | |
AZSQL-004 |
SQL Server has no Azure AD administrator configured | MEDIUM | Azure Cloud | |
AZST-001 |
Storage account allows public blob access | HIGH | Azure Cloud | |
AZVM-002 |
Virtual machine has a public IP address | HIGH | Azure Cloud | |
AZVM-003 |
Virtual machine does not have JIT network access | MEDIUM | Azure Cloud | |
AZVM-005 |
Virtual machine does not use a managed identity | MEDIUM | Azure Cloud | |
BB-004 |
Deploy step missing deployment: environment gate |
MEDIUM | Bitbucket | |
BB-039 |
Agentic CLI output lands without human review | HIGH | 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 | |
CC-038 |
Agentic CLI output lands without human review | HIGH | 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 | |
ENTRA-001 |
Service principal assigned Global Administrator | CRITICAL | Azure Cloud | |
ENTRA-004 |
No Conditional Access policy requiring MFA for admins | HIGH | Azure Cloud | |
ENTRA-005 |
No Conditional Access policy restricting external users | MEDIUM | Azure Cloud | |
GAR-002 |
Artifact Registry repository is publicly readable | HIGH | GCP | |
GCCE-001 |
Compute instance does not have Shielded VM enabled | MEDIUM | GCP | |
GCCE-002 |
Compute instance does not have OS Login enabled | MEDIUM | GCP | |
GCCE-003 |
Compute instance has serial port access enabled | MEDIUM | GCP | |
GCCE-004 |
Compute instance has an external IP address | HIGH | GCP | |
GCCE-005 |
Instance does not block project-wide SSH keys | MEDIUM | GCP | |
GCIAM-001 |
Service account has Owner or Editor role on project | CRITICAL | GCP | |
GCIAM-003 |
Service account token creator granted without constraint | HIGH | GCP | |
GCIAM-004 |
Compute instance uses default service account | HIGH | GCP | |
GCIAM-005 |
Domain-restricted sharing constraint not enforced | MEDIUM | GCP | |
GCKMS-002 |
KMS key IAM policy grants public access | HIGH | GCP | |
GCKMS-004 |
KMS key ring IAM has overly broad bindings | HIGH | GCP | |
GCKMS-005 |
KMS key has primary version scheduled for destruction | MEDIUM | GCP | |
GCNET-001 |
Default VPC network exists in project | MEDIUM | GCP | |
GCNET-002 |
No default-deny ingress firewall rule configured | MEDIUM | GCP | |
GCNET-003 |
Firewall allows SSH or RDP from the internet | CRITICAL | GCP | |
GCNET-004 |
Subnet does not have Private Google Access enabled | MEDIUM | GCP | |
GCNET-005 |
No Cloud NAT gateway configured | LOW | GCP | |
GCRUN-001 |
Cloud Run service allows unauthenticated access | HIGH | GCP | |
GCRUN-002 |
Cloud Run service or function uses default compute SA | HIGH | GCP | |
GCRUN-003 |
Cloud Run service has zero minimum instances | LOW | GCP | |
GCRUN-004 |
Cloud Run service does not use a VPC connector | MEDIUM | GCP | |
GCS-001 |
Cloud Storage bucket is publicly accessible | HIGH | GCP | |
GCS-002 |
Bucket does not enforce uniform bucket-level access | MEDIUM | GCP | |
GCSQL-001 |
Cloud SQL instance has a public IP address | HIGH | GCP | |
GCSQL-002 |
Cloud SQL instance does not have automated backups enabled | MEDIUM | GCP | |
GCSQL-004 |
Cloud SQL instance does not have IAM authentication enabled | MEDIUM | GCP | |
GCSQL-005 |
Cloud SQL instance does not have point-in-time recovery enabled | MEDIUM | GCP | |
GHA-014 |
Deploy job missing environment binding | MEDIUM | GitHub Actions | 🔧 fix |
GHA-123 |
Agentic CLI output lands without human review | HIGH | GitHub Actions | |
GL-004 |
Deploy job lacks manual approval or environment gate | MEDIUM | GitLab CI | |
GL-049 |
Agentic CLI output lands without human review | HIGH | GitLab CI | |
HARNESS-009 |
Agentic CLI output lands without human review | HIGH | Harness CI/CD | |
JF-005 |
Deploy stage missing manual input approval |
MEDIUM | Jenkins | |
JF-024 |
input approval step missing submitter restriction |
MEDIUM | Jenkins | |
JF-038 |
Agentic CLI output lands without human review | HIGH | Jenkins |
ENF-2: L2: Break the build when a violation is detected
Evidenced by 26 checks across 4 providers (AWS, Azure Cloud, GCP, GitLab CI).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
AZMON-001 |
No diagnostic setting for subscription Activity Log | HIGH | Azure Cloud | |
AZMON-002 |
Activity Log retention less than 365 days | MEDIUM | Azure Cloud | |
AZMON-003 |
No alert rule for critical administrative operations | MEDIUM | Azure Cloud | |
AZMON-004 |
Key Vault has no diagnostic settings configured | MEDIUM | Azure Cloud | |
AZMON-005 |
NSG flow log retention less than 90 days | MEDIUM | Azure Cloud | |
AZMON-006 |
Log Analytics workspace retention less than 365 days | MEDIUM | Azure Cloud | |
AZMON-007 |
No service health alert rule configured | LOW | Azure Cloud | |
AZNW-002 |
NSG does not have flow logging enabled | MEDIUM | Azure Cloud | |
AZSQL-002 |
SQL Server auditing not enabled | HIGH | Azure Cloud | |
CP-001 |
No approval action before deploy stages | HIGH | AWS | |
CP-005 |
Production Deploy stage has no preceding ManualApproval | MEDIUM | AWS | |
ENTRA-006 |
No Conditional Access sign-in risk policy | HIGH | Azure Cloud | |
GCLOG-001 |
Cloud Audit Logs not enabled for all services | HIGH | GCP | |
GCLOG-002 |
No log sink configured for audit logs | MEDIUM | GCP | |
GCLOG-003 |
Log bucket retention less than 365 days | MEDIUM | GCP | |
GCLOG-004 |
VPC Flow Logs not enabled on subnet | MEDIUM | GCP | |
GCLOG-005 |
Firewall rule logging not enabled | MEDIUM | GCP | |
GCLOG-006 |
Critical service missing Data Access audit log types | MEDIUM | GCP | |
GCLOG-007 |
No log metric filter for IAM policy changes | MEDIUM | GCP | |
GCLOG-008 |
No log metric filter for firewall rule changes | MEDIUM | GCP | |
GCLOG-009 |
No log metric filter for route changes | MEDIUM | GCP | |
GCLOG-010 |
No log metric filter for Cloud SQL config changes | MEDIUM | GCP | |
GCLOG-011 |
No log metric filter for custom role changes | MEDIUM | GCP | |
GCS-005 |
Cloud Storage bucket access logging not enabled | MEDIUM | GCP | |
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 25 checks across 15 providers (AWS, Argo Workflows, Azure Cloud, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, Drone CI, GCP, GitHub Actions, GitLab CI, Harness CI/CD, Jenkins, Tekton).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ACR-003 |
Container registry content trust not enabled | MEDIUM | Azure Cloud | |
ADO-006 |
Artifacts not signed | MEDIUM | Azure DevOps | |
ARGO-009 |
Artifacts not signed (no cosign/sigstore step) | MEDIUM | Argo Workflows | |
AZSQL-001 |
SQL Server TDE does not use a customer-managed key | MEDIUM | Azure Cloud | |
AZST-003 |
Storage account not encrypted with customer-managed key | MEDIUM | Azure Cloud | |
AZVM-001 |
Virtual machine disks are not encrypted | HIGH | Azure Cloud | |
BB-006 |
Artifacts not signed | MEDIUM | Bitbucket | |
BK-009 |
Artifacts not signed (no cosign/sigstore step) | MEDIUM | Buildkite | |
CA-001 |
CodeArtifact domain has no KMS encryptionKey configured | 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 | |
DR-019 |
Artifacts not signed (no cosign/sigstore step) | MEDIUM | Drone CI | |
ECR-005 |
Repository encrypted with AES256 rather than KMS CMK | MEDIUM | AWS | |
GCB-009 |
Artifacts not signed (no cosign / sigstore step) | MEDIUM | Cloud Build | |
GCKMS-003 |
KMS key not using HSM protection level | LOW | GCP | |
GCKMS-006 |
KMS key uses imported (external) key material | LOW | GCP | |
GCS-004 |
Cloud Storage bucket not encrypted with CMEK | MEDIUM | GCP | |
GHA-006 |
Artifacts not signed (no cosign/sigstore step) | MEDIUM | GitHub Actions | |
GL-006 |
Artifacts not signed | MEDIUM | GitLab CI | |
HARNESS-015 |
Artifacts not signed (no cosign/sigstore step) | MEDIUM | Harness CI/CD | |
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 27 checks across 14 providers (Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, Dockerfile, Drone CI, GitHub Actions, GitLab CI, Harness CI/CD, Helm, Jenkins, OCI manifest, 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 | |
ATTEST-003 |
SBOM contains floating-version dependencies | MEDIUM | OCI manifest | |
ATTEST-004 |
SLSA provenance ships without a resolved-dependencies set | MEDIUM | OCI manifest | |
ATTEST-007 |
SBOM packages lack supplier / originator attribution | LOW | OCI manifest | |
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 | |
DR-020 |
No SBOM produced (no syft / cyclonedx step) | MEDIUM | Drone CI | |
GHA-007 |
SBOM not produced (no CycloneDX/syft/Trivy-SBOM step) | MEDIUM | GitHub Actions | |
GL-007 |
SBOM not produced | MEDIUM | GitLab CI | |
HARNESS-016 |
No SBOM produced (no syft / cyclonedx step) | MEDIUM | Harness CI/CD | |
HELM-002 |
Chart.lock missing per-dependency digests | HIGH | Helm | 🔧 fix |
HELM-005 |
Chart maintainers field empty or missing chain-of-custody info | LOW | Helm | |
HELM-007 |
Chart.yaml description field is empty or missing | LOW | Helm | |
HELM-010 |
Chart.yaml appVersion field is empty or missing | LOW | Helm | |
HELM-011 |
Chart dependency repository URL embeds plaintext credentials | HIGH | Helm | |
HELM-012 |
Chart marked deprecated without naming a successor | MEDIUM | Helm | |
HELM-013 |
Chart.yaml type field missing or invalid | MEDIUM | Helm | |
HELM-014 |
Chart dependency matches a known-compromised chart registry | HIGH | Helm | |
JF-007 |
SBOM not produced | MEDIUM | Jenkins | |
OCI-001 |
Image manifest is missing OCI provenance annotations | MEDIUM | OCI manifest | |
OCI-003 |
Image manifest is missing the image.created annotation |
LOW | OCI manifest | |
OCI-005 |
Image manifest is missing the image.licenses annotation |
LOW | OCI manifest | |
OCI-009 |
Image manifest is missing OCI base-image annotations | MEDIUM | OCI manifest | |
TKN-010 |
No SBOM generated for build artifacts | MEDIUM | Tekton |
REB-4: L4: Digitally sign SBOMs produced (attested provenance)
Evidenced by 16 checks across 12 providers (Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, Drone CI, GitHub Actions, GitLab CI, Harness CI/CD, Jenkins, OCI manifest, 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 | |
ATTEST-001 |
SLSA provenance attests an untrusted builder identity | HIGH | OCI manifest | |
ATTEST-002 |
SLSA provenance source-repo claim is missing or unverifiable | HIGH | OCI manifest | |
ATTEST-005 |
In-toto Statement subject is missing or unpinned | HIGH | OCI manifest | |
ATTEST-006 |
SLSA provenance lacks a meaningful buildType | MEDIUM | OCI manifest | |
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 | |
DR-021 |
No SLSA provenance attestation produced | MEDIUM | Drone CI | |
GHA-024 |
No SLSA provenance attestation produced | MEDIUM | GitHub Actions | |
GL-024 |
No SLSA provenance attestation produced | MEDIUM | GitLab CI | |
HARNESS-017 |
No SLSA provenance attestation produced | MEDIUM | Harness CI/CD | |
JF-028 |
No SLSA provenance attestation produced | MEDIUM | Jenkins | |
OCI-002 |
Image is missing a build attestation manifest | HIGH | OCI manifest | |
TKN-011 |
No SLSA provenance attestation produced | MEDIUM | Tekton |
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.