NIST SP 800-190 Application Container Security
- Version: Final
- URL: https://csrc.nist.gov/pubs/sp/800/190/final
- Source of truth:
pipeline_check/core/standards/data/nist_800_190.py
NIST's Application Container Security Guide. Covers image, registry, runtime, and host hardening for containerized workloads. The scanner evidences the image-build and image-content half of the spec; the runtime-host half (orchestrator hardening at the cluster level) sits outside the scan surface.
At a glance
- Controls in this standard: 12
- Controls evidenced by at least one check: 12 / 12
- Distinct checks evidencing this standard: 548
- Of those, autofixable with
--fix: 112
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 |
|---|---|---|---|
4.1.1 |
Image vulnerabilities, unpatched CVEs baked into images | 16 | 3H · 13M |
4.1.2 |
Image configuration defects, privileged flags, insecure runtime settings | 45 | 9C · 19H · 14M · 3L |
4.1.3 |
Embedded malware in images | 101 | 19C · 72H · 10M |
4.1.4 |
Embedded clear-text secrets in images | 60 | 25C · 26H · 9M |
4.1.5 |
Use of untrusted images, unpinned tags, unknown provenance | 127 | 2C · 54H · 58M · 12L · 1I |
4.2.1 |
Insecure connections to registries (no TLS / cert validation bypassed) | 52 | 44H · 7M · 1L |
4.2.2 |
Stale images in registries, drift and unpatched images | 7 | 1H · 4M · 2L |
4.2.3 |
Insufficient authentication and authorization restrictions on registries | 14 | 2C · 8H · 4M |
4.4.3 |
Unbounded network access from containers, egress not restricted | 32 | 4C · 8H · 17M · 3L |
4.4.4 |
Insecure container runtime configurations, privileged flag, host namespace sharing | 40 | 10C · 22H · 7M · 1L |
4.4.5 |
App vulnerabilities, untrusted code paths reached at runtime | 78 | 14C · 45H · 12M · 7L |
4.4.6 |
Rogue containers, unvetted images executed inside pipeline | 16 | 6H · 9M · 1L |
Filter at runtime
Restrict a scan to checks that evidence this standard with --standard nist_800_190:
# All providers, only checks tied to this standard
pipeline_check --standard nist_800_190
# Compose with --pipeline to scope by provider
pipeline_check --pipeline github --standard nist_800_190
# Compose with another standard to widen the lens
pipeline_check --pipeline aws --standard nist_800_190 --standard owasp_cicd_top_10
Controls in scope
4.1.1: Image vulnerabilities, unpatched CVEs baked into images
Evidenced by 16 checks across 13 providers (AWS, Azure Cloud, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, Drone CI, GCP, GitHub Actions, GitLab CI, Harness CI/CD, Jenkins).
| 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 | |
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 | |
CB-005 |
Outdated managed build image | MEDIUM | AWS | |
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 |
4.1.2: Image configuration defects, privileged flags, insecure runtime settings
Evidenced by 45 checks across 16 providers (AWS, Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, Dockerfile, Drone CI, GCP, GitHub Actions, GitLab CI, Harness CI/CD, Jenkins, Kubernetes, OCI manifest, Tekton).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-017 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | Azure DevOps | 🔧 fix |
ARGO-002 |
Argo template container runs privileged or as root | HIGH | Argo Workflows | |
ARGO-013 |
Argo workflow does not opt out of SA token automount | MEDIUM | Argo Workflows | |
BB-005 |
Step has no max-time, unbounded build |
MEDIUM | Bitbucket | 🔧 fix |
BB-013 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | Bitbucket | 🔧 fix |
BK-005 |
Container started with --privileged or host-bind escalation | HIGH | Buildkite | 🔧 fix |
CB-002 |
Privileged mode enabled | HIGH | AWS | |
CC-017 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | CircleCI | 🔧 fix |
DF-002 |
Container runs as root (missing or root USER directive) | HIGH | Dockerfile | 🔧 fix |
DF-007 |
No HEALTHCHECK directive declared | LOW | Dockerfile | 🔧 fix |
DF-008 |
RUN invokes docker --privileged or escalates capabilities | HIGH | Dockerfile | |
DF-011 |
Package manager install without cache cleanup in same layer | LOW | Dockerfile | |
DF-012 |
RUN invokes sudo | HIGH | Dockerfile | |
DF-013 |
EXPOSE declares sensitive remote-access port | CRITICAL | Dockerfile | 🔧 fix |
DF-014 |
WORKDIR set to a system / kernel filesystem path | CRITICAL | Dockerfile | |
DF-015 |
RUN grants world-writable permissions (chmod 777 / a+w) | MEDIUM | Dockerfile | |
DF-017 |
ENV PATH prepends a world-writable directory | MEDIUM | Dockerfile | 🔧 fix |
DF-018 |
RUN chown rewrites ownership of a system path | MEDIUM | Dockerfile | |
DF-023 |
ENV sets a dynamic-loader hijack variable | HIGH | Dockerfile | |
DF-030 |
ENV NODE_OPTIONS preloads code or opens an inspector | MEDIUM | Dockerfile | |
DR-002 |
Step runs with privileged: true | HIGH | Drone CI | |
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-005 |
Instance does not block project-wide SSH keys | MEDIUM | GCP | |
GCRUN-002 |
Cloud Run service or function uses default compute SA | HIGH | GCP | |
GHA-017 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | GitHub Actions | 🔧 fix |
GHA-026 |
Container job disables isolation via options: |
HIGH | GitHub Actions | |
GL-017 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | GitLab CI | 🔧 fix |
GL-039 |
Docker-in-Docker service exposes an unauthenticated daemon | HIGH | GitLab CI | |
HARNESS-003 |
Step runs with privileged: true | HIGH | Harness CI/CD | |
JF-017 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | Jenkins | 🔧 fix |
JF-025 |
Kubernetes agent pod template runs privileged or mounts hostPath | HIGH | Jenkins | |
K8S-005 |
Container securityContext.privileged: true | CRITICAL | Kubernetes | 🔧 fix |
K8S-006 |
Container allowPrivilegeEscalation not explicitly false | HIGH | Kubernetes | 🔧 fix |
K8S-007 |
Container runAsNonRoot not true / runAsUser is 0 | HIGH | Kubernetes | 🔧 fix |
K8S-008 |
Container readOnlyRootFilesystem not true | MEDIUM | Kubernetes | 🔧 fix |
K8S-009 |
Container capabilities not dropping ALL / adding dangerous caps | HIGH | Kubernetes | |
K8S-010 |
Container seccompProfile not RuntimeDefault or Localhost | MEDIUM | Kubernetes | |
K8S-011 |
Pod serviceAccountName unset or 'default' | MEDIUM | Kubernetes | |
K8S-012 |
Pod automountServiceAccountToken not false | MEDIUM | Kubernetes | |
K8S-039 |
Pod uses shareProcessNamespace: true | MEDIUM | Kubernetes | |
K8S-040 |
Container securityContext.procMount: Unmasked | HIGH | Kubernetes | |
OCI-006 |
Image has an excessive layer count | LOW | OCI manifest | |
TKN-002 |
Tekton step runs privileged or as root | HIGH | Tekton | |
TKN-013 |
Tekton sidecar runs privileged or as root | HIGH | Tekton |
4.1.3: Embedded malware in images
Evidenced by 101 checks across 20 providers (AWS, Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, Composer, Drone CI, GitHub Actions, GitLab CI, Harness CI/CD, Helm, Jenkins, NuGet, PyPI, RubyGems, Tekton, maven, npm).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-002 |
Script injection via attacker-controllable context | HIGH | Azure DevOps | |
ADO-016 |
Remote script piped to shell interpreter | HIGH | Azure DevOps | 🔧 fix |
ADO-026 |
Pipeline contains indicators of malicious activity | CRITICAL | Azure DevOps | |
ADO-027 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | Azure DevOps | |
ADO-034 |
ML model loaded with trust_remote_code (code execution) | HIGH | Azure DevOps | |
ADO-035 |
Untrusted PR/commit context reaches an agentic AI CLI (prompt injection) | HIGH | Azure DevOps | |
ADO-036 |
Unsafe deserialization of a fetched artifact (pickle RCE) | HIGH | Azure DevOps | |
ARGO-019 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | Argo Workflows | |
BB-002 |
Script injection via attacker-controllable context | HIGH | Bitbucket | |
BB-012 |
Remote script piped to shell interpreter | HIGH | Bitbucket | 🔧 fix |
BB-025 |
Pipeline contains indicators of malicious activity | CRITICAL | Bitbucket | |
BB-026 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | Bitbucket | |
BB-035 |
ML model loaded with trust_remote_code (code execution) | HIGH | Bitbucket | |
BB-036 |
Untrusted PR/branch context reaches an agentic AI CLI (prompt injection) | HIGH | Bitbucket | |
BB-037 |
Unsafe deserialization of a fetched artifact (pickle RCE) | HIGH | Bitbucket | |
BK-016 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | Buildkite | |
CB-011 |
CodeBuild buildspec contains indicators of malicious activity | CRITICAL | AWS | |
CC-002 |
Script injection via untrusted environment variable | HIGH | CircleCI | |
CC-016 |
Remote script piped to shell interpreter | HIGH | CircleCI | 🔧 fix |
CC-026 |
Config contains indicators of malicious activity | CRITICAL | CircleCI | |
CC-027 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | CircleCI | |
CC-034 |
ML model loaded with trust_remote_code (code execution) | HIGH | CircleCI | |
CC-036 |
Unsafe deserialization of a fetched artifact (pickle RCE) | HIGH | CircleCI | |
CC-037 |
Untrusted PR/build context reaches an agentic AI CLI (prompt injection) | 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 | |
COMPOSER-005 |
composer.json minimum-stability accepts unstable releases | MEDIUM | Composer | |
COMPOSER-006 |
composer.json scripts hook pipes a remote download to a shell | HIGH | Composer | |
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 | |
COMPOSER-014 |
composer.json minimum-stability lowered without prefer-stable | MEDIUM | Composer | |
DR-017 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | Drone CI | |
GCB-004 |
dynamicSubstitutions on with user substitutions in step args | HIGH | Cloud Build | |
GCB-006 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | Cloud Build | |
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 | |
GEM-006 |
Gemfile requires a known-compromised gem version | HIGH | RubyGems | |
GEM-007 |
Gemfile declares multiple top-level sources without scoping | MEDIUM | RubyGems | |
GEM-008 |
Gemfile gem declared with a path: source | HIGH | RubyGems | |
GEM-010 |
Gemfile uses dynamic gem-list resolution | MEDIUM | RubyGems | |
GEM-011 |
Gemfile registers a Bundler plugin that runs at install time | HIGH | RubyGems | |
GEM-012 |
Gemfile gem pinned to a per-gem :source | MEDIUM | RubyGems | |
GEM-013 |
Gemfile git gem fetched over an insecure transport | HIGH | RubyGems | |
GHA-003 |
Script injection via untrusted context | HIGH | GitHub Actions | 🔧 fix |
GHA-016 |
Remote script piped to shell interpreter | HIGH | GitHub Actions | 🔧 fix |
GHA-027 |
Workflow contains indicators of malicious activity | CRITICAL | GitHub Actions | |
GHA-028 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | 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-117 |
IaC apply on an untrusted pull_request trigger | CRITICAL | GitHub Actions | |
GHA-118 |
Untrusted content written to $GITHUB_ENV / $GITHUB_PATH | HIGH | GitHub Actions | |
GHA-119 |
Untrusted context reaches an agentic AI CLI (prompt injection) | HIGH | GitHub Actions | |
GHA-120 |
ML model loaded with trust_remote_code (code execution) | HIGH | GitHub Actions | |
GHA-122 |
Unsafe deserialization of a fetched artifact (pickle RCE) | HIGH | GitHub Actions | |
GL-002 |
Script injection via untrusted commit/MR context | HIGH | GitLab CI | |
GL-016 |
Remote script piped to shell interpreter | HIGH | GitLab CI | 🔧 fix |
GL-025 |
Pipeline contains indicators of malicious activity | CRITICAL | GitLab CI | |
GL-026 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | GitLab CI | |
GL-041 |
IaC apply on an untrusted merge-request trigger | CRITICAL | GitLab CI | |
GL-045 |
ML model loaded with trust_remote_code (code execution) | HIGH | GitLab CI | |
GL-047 |
Unsafe deserialization of a fetched artifact (pickle RCE) | HIGH | GitLab CI | |
GL-048 |
Untrusted MR/commit context reaches an agentic AI CLI (prompt injection) | HIGH | GitLab CI | |
HARNESS-008 |
Untrusted context reaches an agentic AI CLI (prompt injection) | HIGH | Harness CI/CD | |
HARNESS-010 |
ML model loaded with trust_remote_code (code execution) | HIGH | Harness CI/CD | |
HARNESS-011 |
Unsafe deserialization of a fetched artifact (pickle RCE) | HIGH | Harness CI/CD | |
HARNESS-014 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | Harness CI/CD | |
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-002 |
Script step interpolates attacker-controllable env var | HIGH | Jenkins | |
JF-016 |
Remote script piped to shell interpreter | HIGH | Jenkins | 🔧 fix |
JF-029 |
Jenkinsfile contains indicators of malicious activity | CRITICAL | Jenkins | |
JF-030 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | Jenkins | |
JF-037 |
Untrusted PR/build context reaches an agentic AI CLI (prompt injection) | HIGH | Jenkins | |
JF-039 |
ML model loaded with trust_remote_code (code execution) | HIGH | Jenkins | |
JF-041 |
Unsafe deserialization of a fetched artifact (pickle RCE) | HIGH | 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 | |
MVN-014 |
Maven Wrapper distributionUrl lacks distributionSha256Sum | MEDIUM | maven | |
MVN-015 |
pom.xml binds a build-time code-execution plugin to the lifecycle | HIGH | maven | |
MVN-016 |
build.gradle re-enables HTTP via allowInsecureProtocol = true | HIGH | maven | |
MVN-018 |
distributionManagement release repository accepts SNAPSHOTs | 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 | |
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-015 |
PackageReference VersionOverride defeats Central Package Management | MEDIUM | 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-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 | |
TKN-018 |
Dangerous shell idiom (eval, sh -c variable, backtick exec) | HIGH | Tekton |
4.1.4: Embedded clear-text secrets in images
Evidenced by 60 checks across 21 providers (AWS, Argo Workflows, Azure Cloud, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, Developer environment, Dockerfile, Drone CI, GitHub Actions, GitLab CI, Harness CI/CD, Helm, Jenkins, Kubernetes, NuGet, Tekton, maven, npm).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-003 |
Variables contain literal secret values | CRITICAL | Azure DevOps | |
ADO-008 |
Credential-shaped literal in pipeline body | CRITICAL | Azure DevOps | 🔧 fix |
ADO-014 |
AWS auth uses long-lived access keys | MEDIUM | Azure DevOps | 🔧 fix |
AKV-001 |
Key Vault soft delete not enabled | HIGH | Azure Cloud | |
AKV-002 |
Key Vault purge protection not enabled | HIGH | Azure Cloud | |
ARGO-006 |
Literal secret value in Argo template env or parameter default | CRITICAL | Argo Workflows | 🔧 fix |
AZVM-001 |
Virtual machine disks are not encrypted | HIGH | Azure Cloud | |
BB-003 |
Variables contain literal secret values | CRITICAL | Bitbucket | |
BB-008 |
Credential-shaped literal in pipeline body | CRITICAL | Bitbucket | 🔧 fix |
BB-011 |
AWS auth uses long-lived access keys | MEDIUM | Bitbucket | 🔧 fix |
BB-017 |
Repository token written to persistent storage | CRITICAL | Bitbucket | 🔧 fix |
BB-019 |
after-script references secrets | HIGH | Bitbucket | |
BK-002 |
Literal secret value in pipeline env block | CRITICAL | Buildkite | 🔧 fix |
CB-001 |
Secrets in plaintext environment variables | CRITICAL | AWS | |
CB-006 |
CodeBuild source auth uses long-lived token | HIGH | AWS | |
CC-004 |
Secret-like environment variable not managed via context | MEDIUM | CircleCI | |
CC-005 |
AWS auth uses long-lived access keys in environment block | MEDIUM | CircleCI | 🔧 fix |
CC-008 |
Credential-shaped literal in config body | CRITICAL | CircleCI | 🔧 fix |
CC-019 |
add_ssh_keys without fingerprint restriction |
HIGH | CircleCI | |
CP-004 |
Legacy ThirdParty/GitHub source action (OAuth token) | HIGH | AWS | |
DEV-008 |
Credential-shaped literal in a developer-environment config | CRITICAL | Developer environment | |
DF-006 |
ENV or ARG carries a credential-shaped literal value | CRITICAL | Dockerfile | |
DF-019 |
COPY/ADD source path looks like a credential file | HIGH | Dockerfile | 🔧 fix |
DF-020 |
ARG declares a credential-named build argument | HIGH | Dockerfile | 🔧 fix |
DF-025 |
RUN writes a registry auth token into a Docker layer | CRITICAL | Dockerfile | |
DR-004 |
Literal credential in step environment / settings | CRITICAL | Drone CI | |
GCB-003 |
Secret Manager value referenced in step args | HIGH | Cloud Build | |
GCB-012 |
Credential-shaped literal in pipeline body | CRITICAL | Cloud Build | 🔧 fix |
GCB-018 |
Legacy KMS secrets block in use (prefer availableSecrets / Secret Manager) | MEDIUM | Cloud Build | |
GHA-005 |
AWS auth uses long-lived access keys | MEDIUM | GitHub Actions | 🔧 fix |
GHA-008 |
Credential-shaped literal in workflow body | CRITICAL | GitHub Actions | 🔧 fix |
GHA-033 |
Secret value echoed / printed in a run: block | CRITICAL | GitHub Actions | |
GHA-034 |
Reusable workflow called with secrets: inherit | MEDIUM | GitHub Actions | 🔧 fix |
GHA-037 |
actions/checkout persists GITHUB_TOKEN into .git/config | HIGH | GitHub Actions | 🔧 fix |
GHA-039 |
services / container credentials embedded as literal in workflow | CRITICAL | GitHub Actions | |
GHA-054 |
actions/checkout with ssh-key persists SSH credential in repo | HIGH | GitHub Actions | 🔧 fix |
GHA-055 |
Reusable workflow outputs derive a secret or caller-input value | HIGH | GitHub Actions | |
GHA-116 |
Workflow serializes the entire secrets context (toJSON(secrets)) | HIGH | GitHub Actions | |
GL-003 |
Variables contain literal secret values | CRITICAL | GitLab CI | |
GL-008 |
Credential-shaped literal in pipeline body | CRITICAL | GitLab CI | 🔧 fix |
GL-013 |
AWS auth uses long-lived access keys | MEDIUM | GitLab CI | 🔧 fix |
GL-020 |
CI_JOB_TOKEN written to persistent storage | CRITICAL | GitLab CI | 🔧 fix |
HARNESS-004 |
Literal credential in a pipeline / stage variable | CRITICAL | Harness CI/CD | 🔧 fix |
HELM-016 |
values.yaml ships a default secret or credential | HIGH | Helm | |
JF-004 |
AWS auth uses long-lived access keys via withCredentials | MEDIUM | Jenkins | 🔧 fix |
JF-008 |
Credential-shaped literal in pipeline body | CRITICAL | Jenkins | 🔧 fix |
JF-010 |
Long-lived AWS keys exposed via environment {} block | HIGH | Jenkins | 🔧 fix |
JF-033 |
withCredentials secret leaked via Groovy ${...} interpolation in sh step | HIGH | Jenkins | |
JF-034 |
Pipeline declares a password() build parameter | HIGH | Jenkins | |
K8S-017 |
Container env value carries a credential-shaped literal | CRITICAL | Kubernetes | |
K8S-018 |
Secret stringData/data carries a credential-shaped literal | CRITICAL | Kubernetes | |
K8S-037 |
ConfigMap data carries a credential-shaped literal | HIGH | Kubernetes | |
LMB-003 |
Lambda function env vars may contain plaintext secrets | HIGH | AWS | |
MVN-010 |
settings.xml |
HIGH | maven | |
MVN-011 |
Maven repository URL embeds plaintext credentials | HIGH | maven | |
MVN-017 |
settings.xml |
HIGH | maven | |
NPM-011 |
package.json files field includes secret-shaped paths | HIGH | npm | |
NPM-013 |
package.json files field uses an overly broad pattern | HIGH | npm | |
NUGET-014 |
NuGet.config source URL embeds plaintext credentials | HIGH | NuGet | |
TKN-005 |
Literal secret value in Tekton step env or param default | CRITICAL | Tekton | 🔧 fix |
4.1.5: Use of untrusted images, unpinned tags, unknown provenance
Evidenced by 127 checks across 24 providers (AWS, Argo Workflows, Azure Cloud, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, Dockerfile, Drone CI, GitHub Actions, GitLab CI, Harness CI/CD, Helm, Jenkins, Kubernetes, Modelfile, NuGet, OCI manifest, PyPI, SCM, Tekton, maven, npm).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ACR-003 |
Container registry content trust not enabled | MEDIUM | Azure Cloud | |
ACR-005 |
Container registry tag immutability (verify per-repository locking) | INFO | Azure Cloud | |
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-018 |
Package install from insecure source | HIGH | Azure DevOps | 🔧 fix |
ADO-021 |
Package install without lockfile enforcement | MEDIUM | Azure DevOps | 🔧 fix |
ADO-022 |
Dependency update command bypasses lockfile pins | MEDIUM | Azure DevOps | 🔧 fix |
ADO-025 |
Cross-repo template not pinned to commit SHA | HIGH | Azure DevOps | |
ADO-028 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | Azure DevOps | |
ARGO-001 |
Argo template container image not pinned to a digest | HIGH | Argo Workflows | |
ARGO-014 |
Argo template script runs unpinned package install | MEDIUM | 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-014 |
Package install from insecure source | HIGH | Bitbucket | 🔧 fix |
BB-021 |
Package install without lockfile enforcement | MEDIUM | Bitbucket | 🔧 fix |
BB-022 |
Dependency update command bypasses lockfile pins | MEDIUM | Bitbucket | 🔧 fix |
BB-027 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | Bitbucket | |
BB-029 |
image: (step or service) not pinned by sha256 digest | HIGH | Bitbucket | |
BB-030 |
npm install without registry-signature verification step | MEDIUM | Bitbucket | |
BB-031 |
pip install without --require-hashes verification |
MEDIUM | Bitbucket | |
BK-001 |
Buildkite plugin not pinned to an exact version | HIGH | Buildkite | |
BK-014 |
Step commands run unpinned package installs | MEDIUM | Buildkite | |
CA-002 |
CodeArtifact repository has a public external connection | HIGH | 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-018 |
Package install from insecure source | HIGH | CircleCI | 🔧 fix |
CC-021 |
Package install without lockfile enforcement | MEDIUM | CircleCI | 🔧 fix |
CC-022 |
Dependency update command bypasses lockfile pins | MEDIUM | CircleCI | 🔧 fix |
CC-028 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | CircleCI | |
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-009 |
ADD used where COPY would suffice | LOW | Dockerfile | |
DF-016 |
Image lacks OCI provenance labels | 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 | |
DR-010 |
Step commands run unpinned package installs | MEDIUM | Drone CI | |
DR-012 |
Service container image not pinned to digest | HIGH | Drone CI | |
DR-014 |
Step pipes a remote download into a shell interpreter | HIGH | Drone CI | 🔧 fix |
ECR-002 |
Image tags are mutable | HIGH | AWS | |
ECR-006 |
ECR pull-through cache rule uses an untrusted upstream | HIGH | AWS | |
GCB-001 |
Cloud Build step image not pinned by digest | HIGH | Cloud Build | 🔧 fix |
GCB-007 |
availableSecrets references versions/latest |
MEDIUM | Cloud Build | 🔧 fix |
GCB-013 |
Package install bypasses registry integrity (git / path / tarball) | MEDIUM | Cloud Build | |
GHA-001 |
Action not pinned to commit SHA | HIGH | GitHub Actions | 🔧 fix |
GHA-018 |
Package install from insecure source | HIGH | GitHub Actions | 🔧 fix |
GHA-019 |
GITHUB_TOKEN written to persistent storage | CRITICAL | 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 | |
GHA-029 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | GitHub Actions | |
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-051 |
services / container image is not pinned by digest | 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-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-018 |
Package install from insecure source | HIGH | GitLab CI | 🔧 fix |
GL-021 |
Package install without lockfile enforcement | MEDIUM | GitLab CI | 🔧 fix |
GL-022 |
Dependency update command bypasses lockfile pins | MEDIUM | GitLab CI | 🔧 fix |
GL-027 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | GitLab CI | |
GL-028 |
services: image not pinned | HIGH | GitLab CI | |
GL-030 |
trigger: include: pulls child pipeline without pinned ref | HIGH | 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 | |
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 | |
HARNESS-005 |
Step pipes a remote download into a shell interpreter | HIGH | Harness CI/CD | 🔧 fix |
HELM-001 |
Chart.yaml declares legacy apiVersion: v1 | MEDIUM | Helm | 🔧 fix |
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-005 |
Chart maintainers field empty or missing chain-of-custody info | LOW | Helm | |
HELM-006 |
Chart.yaml does not declare a kubeVersion compatibility range | 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-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-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-018 |
Package install from insecure source | HIGH | Jenkins | 🔧 fix |
JF-021 |
Package install without lockfile enforcement | MEDIUM | Jenkins | 🔧 fix |
JF-022 |
Dependency update command bypasses lockfile pins | MEDIUM | Jenkins | 🔧 fix |
JF-031 |
Package install bypasses registry integrity (git / path / tarball source) | MEDIUM | Jenkins | |
K8S-001 |
Container image not pinned by sha256 digest | HIGH | Kubernetes | 🔧 fix |
K8S-036 |
ServiceAccount imagePullSecrets references missing Secret | MEDIUM | Kubernetes | |
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 | |
NPM-009 |
New transitive dependency added since the base 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-001 |
Image manifest is missing OCI provenance annotations | MEDIUM | OCI manifest | |
OCI-002 |
Image is missing a build attestation manifest | HIGH | 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-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 | |
OCI-009 |
Image manifest is missing OCI base-image annotations | MEDIUM | 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 | |
SCM-022 |
Repo Actions permissions allow any source (no allow-list) | MEDIUM | SCM | |
TKN-001 |
Tekton step image not pinned to a digest | HIGH | Tekton | |
TKN-014 |
Tekton step script runs unpinned package install | MEDIUM | Tekton | |
TKN-016 |
Remote resolver taskRef / pipelineRef not pinned to an immutable revision | HIGH | Tekton |
4.2.1: Insecure connections to registries (no TLS / cert validation bypassed)
Evidenced by 52 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, NuGet, OCI manifest, PyPI, RubyGems, Tekton, maven, npm).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-023 |
TLS / certificate verification bypass | HIGH | Azure DevOps | 🔧 fix |
ARGO-008 |
Argo script source pipes remote install or disables TLS | HIGH | Argo Workflows | 🔧 fix |
ARGO-015 |
Input artifact pulls from an insecure (non-HTTPS) URL | HIGH | Argo Workflows | |
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-023 |
TLS / certificate verification bypass | HIGH | Bitbucket | 🔧 fix |
BK-004 |
Remote script piped into shell interpreter | HIGH | Buildkite | 🔧 fix |
BK-008 |
TLS verification disabled in step command | MEDIUM | Buildkite | 🔧 fix |
CC-023 |
TLS / certificate verification bypass | HIGH | CircleCI | 🔧 fix |
COMPOSER-003 |
composer.json repository declared over plain HTTP | 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 | |
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-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 | |
DR-006 |
TLS verification disabled in step commands | HIGH | Drone CI | 🔧 fix |
GCB-010 |
Remote script piped to shell interpreter | HIGH | Cloud Build | |
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 | |
GHA-022 |
Dependency update command bypasses lockfile pins | MEDIUM | GitHub Actions | 🔧 fix |
GHA-023 |
TLS / certificate verification bypass | HIGH | GitHub Actions | 🔧 fix |
GL-023 |
TLS / certificate verification bypass | HIGH | GitLab CI | 🔧 fix |
HARNESS-006 |
TLS verification disabled in step commands | HIGH | Harness CI/CD | 🔧 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 | |
HELM-011 |
Chart dependency repository URL embeds plaintext credentials | HIGH | Helm | |
JF-023 |
TLS / certificate verification bypass | HIGH | Jenkins | 🔧 fix |
JF-035 |
httpRequest step disables SSL verification | HIGH | Jenkins | |
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 | |
NUGET-004 |
HTTP-only NuGet package source | HIGH | NuGet | |
NUGET-007 |
Multiple NuGet sources without packageSourceMapping | HIGH | NuGet | |
NUGET-016 |
Private feed without |
HIGH | NuGet | |
NUGET-017 |
Public gallery active alongside a private feed, not disabled | HIGH | NuGet | |
OCI-004 |
Image layer references an arbitrary URL (foreign layer) | HIGH | OCI manifest | |
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 | |
S3-005 |
Artifact bucket missing aws:SecureTransport deny | MEDIUM | AWS | |
TKN-008 |
Tekton step script pipes remote install or disables TLS | HIGH | Tekton | 🔧 fix |
4.2.2: Stale images in registries, drift and unpatched images
Evidenced by 7 checks across 5 providers (AWS, Cloud Build, Dockerfile, GCP, Helm).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
CB-005 |
Outdated managed build image | MEDIUM | AWS | |
DF-010 |
apt-get dist-upgrade / upgrade pulls unknown package versions | LOW | Dockerfile | |
ECR-002 |
Image tags are mutable | HIGH | AWS | |
ECR-004 |
No lifecycle policy configured | LOW | AWS | |
GAR-003 |
Artifact Registry has no cleanup policy | MEDIUM | GCP | |
GCB-007 |
availableSecrets references versions/latest |
MEDIUM | Cloud Build | 🔧 fix |
HELM-008 |
Chart.lock generated more than 90 days ago | MEDIUM | Helm |
4.2.3: Insufficient authentication and authorization restrictions on registries
Evidenced by 14 checks across 3 providers (AWS, Azure Cloud, GCP).
| 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 | |
AKV-003 |
Key Vault allows access from all networks | MEDIUM | Azure Cloud | |
AZST-001 |
Storage account allows public blob access | HIGH | Azure Cloud | |
AZST-003 |
Storage account not encrypted with customer-managed key | MEDIUM | Azure Cloud | |
CA-003 |
CodeArtifact domain policy allows cross-account wildcard | CRITICAL | AWS | |
CA-004 |
CodeArtifact repo policy grants codeartifact:* with Resource '*' |
HIGH | AWS | |
ECR-003 |
Repository policy allows public access | CRITICAL | AWS | |
ECR-005 |
Repository encrypted with AES256 rather than KMS CMK | MEDIUM | AWS | |
GAR-002 |
Artifact Registry repository is publicly readable | HIGH | GCP | |
GCKMS-002 |
KMS key IAM policy grants public access | HIGH | GCP | |
GCRUN-001 |
Cloud Run service allows unauthenticated access | HIGH | GCP | |
GCS-001 |
Cloud Storage bucket is publicly accessible | HIGH | GCP | |
GCS-002 |
Bucket does not enforce uniform bucket-level access | MEDIUM | GCP |
4.4.3: Unbounded network access from containers, egress not restricted
Evidenced by 32 checks across 11 providers (AWS, Azure Cloud, Azure DevOps, Bitbucket, CircleCI, Cloud Build, Dockerfile, GCP, GitHub Actions, GitLab CI, Jenkins).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-013 |
Self-hosted pool without explicit ephemeral marker | MEDIUM | Azure DevOps | |
AZNW-001 |
NSG allows inbound SSH or RDP from the internet | CRITICAL | Azure Cloud | |
AZNW-002 |
NSG does not have flow logging enabled | MEDIUM | 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 | |
AZVM-002 |
Virtual machine has a public IP address | HIGH | Azure Cloud | |
BB-016 |
Self-hosted runner without ephemeral marker | MEDIUM | Bitbucket | |
CC-010 |
Self-hosted runner without ephemeral marker | MEDIUM | CircleCI | |
CC-014 |
Job missing resource_class declaration |
MEDIUM | CircleCI | |
DF-013 |
EXPOSE declares sensitive remote-access port | CRITICAL | Dockerfile | 🔧 fix |
GCB-021 |
No private worker pool, build runs on the shared default pool | MEDIUM | Cloud Build | 🔧 fix |
GCCE-004 |
Compute instance has an external IP address | HIGH | 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-004 |
Cloud Run service does not use a VPC connector | MEDIUM | GCP | |
GCSQL-001 |
Cloud SQL instance has a public IP address | HIGH | GCP | |
GHA-012 |
Self-hosted runner without ephemeral marker | MEDIUM | GitHub Actions | |
GHA-026 |
Container job disables isolation via options: |
HIGH | GitHub Actions | |
GHA-057 |
Secret-scanner output sent to network egress | CRITICAL | GitHub Actions | |
GHA-105 |
Self-hosted runner reachable from an untrusted PR trigger | HIGH | GitHub Actions | |
GHA-107 |
harden-runner runs in audit mode (egress not blocked) | MEDIUM | GitHub Actions | |
GHA-108 |
Sensitive workflow has no runtime egress control | LOW | GitHub Actions | |
GHA-109 |
harden-runner is not the first step in the job | LOW | GitHub Actions | |
GL-014 |
Self-managed runner without ephemeral tag | MEDIUM | GitLab CI | |
JF-014 |
Agent label missing ephemeral marker | MEDIUM | Jenkins | |
PBAC-001 |
CodeBuild project has no VPC configuration | HIGH | AWS | |
PBAC-002 |
CodeBuild service role shared across multiple projects | MEDIUM | AWS | |
PBAC-003 |
CodeBuild security group allows 0.0.0.0/0 all-port egress | MEDIUM | AWS |
4.4.4: Insecure container runtime configurations, privileged flag, host namespace sharing
Evidenced by 40 checks across 15 providers (AWS, Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, Dockerfile, Drone CI, GCP, GitHub Actions, GitLab CI, Harness CI/CD, Jenkins, Kubernetes, Tekton).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-017 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | Azure DevOps | 🔧 fix |
ARGO-002 |
Argo template container runs privileged or as root | HIGH | Argo Workflows | |
ARGO-004 |
Argo workflow mounts hostPath or shares host namespaces | CRITICAL | Argo Workflows | |
BB-005 |
Step has no max-time, unbounded build |
MEDIUM | Bitbucket | 🔧 fix |
BB-013 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | Bitbucket | 🔧 fix |
BK-005 |
Container started with --privileged or host-bind escalation | HIGH | Buildkite | 🔧 fix |
CB-002 |
Privileged mode enabled | HIGH | AWS | |
CC-017 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | CircleCI | 🔧 fix |
DF-002 |
Container runs as root (missing or root USER directive) | HIGH | Dockerfile | 🔧 fix |
DF-008 |
RUN invokes docker --privileged or escalates capabilities | HIGH | Dockerfile | |
DF-012 |
RUN invokes sudo | HIGH | Dockerfile | |
DR-002 |
Step runs with privileged: true | HIGH | Drone CI | |
DR-007 |
Step mounts a sensitive host path | HIGH | Drone CI | |
GCCE-003 |
Compute instance has serial port access enabled | MEDIUM | GCP | |
GHA-017 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | GitHub Actions | 🔧 fix |
GL-017 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | GitLab CI | 🔧 fix |
GL-039 |
Docker-in-Docker service exposes an unauthenticated daemon | HIGH | GitLab CI | |
HARNESS-003 |
Step runs with privileged: true | HIGH | Harness CI/CD | |
HARNESS-007 |
Stage infrastructure mounts a sensitive host path | HIGH | Harness CI/CD | |
JF-017 |
Docker run with insecure flags (privileged/host mount) | CRITICAL | Jenkins | 🔧 fix |
JF-025 |
Kubernetes agent pod template runs privileged or mounts hostPath | HIGH | Jenkins | |
K8S-002 |
Pod hostNetwork: true | HIGH | Kubernetes | 🔧 fix |
K8S-003 |
Pod hostPID: true | HIGH | Kubernetes | 🔧 fix |
K8S-004 |
Pod hostIPC: true | HIGH | Kubernetes | 🔧 fix |
K8S-005 |
Container securityContext.privileged: true | CRITICAL | Kubernetes | 🔧 fix |
K8S-006 |
Container allowPrivilegeEscalation not explicitly false | HIGH | Kubernetes | 🔧 fix |
K8S-007 |
Container runAsNonRoot not true / runAsUser is 0 | HIGH | Kubernetes | 🔧 fix |
K8S-008 |
Container readOnlyRootFilesystem not true | MEDIUM | Kubernetes | 🔧 fix |
K8S-009 |
Container capabilities not dropping ALL / adding dangerous caps | HIGH | Kubernetes | |
K8S-010 |
Container seccompProfile not RuntimeDefault or Localhost | MEDIUM | Kubernetes | |
K8S-013 |
Pod uses a hostPath volume | HIGH | Kubernetes | 🔧 fix |
K8S-014 |
Pod hostPath references a sensitive host directory | CRITICAL | Kubernetes | |
K8S-015 |
Container missing resources.limits.memory | MEDIUM | Kubernetes | |
K8S-016 |
Container missing resources.limits.cpu | LOW | Kubernetes | |
K8S-022 |
Service exposes SSH (port 22) | MEDIUM | Kubernetes | |
K8S-039 |
Pod uses shareProcessNamespace: true | MEDIUM | Kubernetes | |
K8S-040 |
Container securityContext.procMount: Unmasked | HIGH | Kubernetes | |
TKN-002 |
Tekton step runs privileged or as root | HIGH | Tekton | |
TKN-004 |
Tekton Task mounts hostPath or shares host namespaces | CRITICAL | Tekton | |
TKN-013 |
Tekton sidecar runs privileged or as root | HIGH | Tekton |
4.4.5: App vulnerabilities, untrusted code paths reached at runtime
Evidenced by 78 checks across 18 providers (AWS, Argo Workflows, Azure DevOps, Bitbucket, Buildkite, CircleCI, Cloud Build, Composer, Dockerfile, Drone CI, GitHub Actions, GitLab CI, Harness CI/CD, Jenkins, NuGet, RubyGems, Tekton, npm).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-010 |
Cross-pipeline download: ingestion unverified |
CRITICAL | Azure DevOps | |
ADO-011 |
template: <local-path> on PR-validated pipeline |
HIGH | Azure DevOps | |
ADO-015 |
Job has no timeoutInMinutes, unbounded build |
MEDIUM | Azure DevOps | 🔧 fix |
ADO-019 |
extends: template on PR-validated pipeline points to local path |
CRITICAL | Azure DevOps | |
ADO-030 |
pool interpolates attacker-controllable value | HIGH | Azure DevOps | 🔧 fix |
ARGO-005 |
Argo input parameter interpolated unsafely in script / args | CRITICAL | Argo Workflows | |
ARGO-007 |
Argo workflow has no activeDeadlineSeconds | LOW | Argo Workflows | |
ARGO-017 |
Argo resource template applies a manifest built from an untrusted parameter | CRITICAL | Argo Workflows | |
BB-010 |
Deploy step ingests pull-request artifact unverified | CRITICAL | Bitbucket | |
BK-003 |
Untrusted Buildkite variable interpolated in command | HIGH | Buildkite | |
BK-006 |
Step has no timeout_in_minutes | LOW | Buildkite | |
BK-015 |
agents map interpolates attacker-controllable Buildkite variable | HIGH | Buildkite | |
CB-004 |
Build timeout missing or at the AWS maximum (480 min) | LOW | AWS | |
CB-010 |
CodeBuild webhook allows fork-PR builds without actor filtering | HIGH | AWS | |
CC-012 |
Dynamic config via setup: true enables code injection |
MEDIUM | CircleCI | |
CC-015 |
No no_output_timeout configured |
MEDIUM | CircleCI | 🔧 fix |
COMPOSER-004 |
composer.json repository URL embeds plaintext credentials | HIGH | Composer | |
COMPOSER-009 |
auth.json committed alongside composer.json with literal credentials | HIGH | Composer | |
DF-005 |
RUN uses shell-eval (eval / sh -c on a variable / backticks) | HIGH | Dockerfile | |
DF-023 |
ENV sets a dynamic-loader hijack variable | HIGH | Dockerfile | |
DF-024 |
RUN npm/yarn/pnpm install runs lifecycle scripts | HIGH | Dockerfile | |
DF-030 |
ENV NODE_OPTIONS preloads code or opens an inspector | MEDIUM | Dockerfile | |
DR-003 |
Untrusted Drone template variable in shell command | HIGH | Drone CI | |
DR-011 |
node map interpolates attacker-controllable Drone variable | HIGH | Drone CI | |
DR-013 |
Pipeline defines no trigger event filter | MEDIUM | Drone CI | |
DR-014 |
Step pipes a remote download into a shell interpreter | HIGH | Drone CI | 🔧 fix |
DR-015 |
Pipeline clone enables recursive submodule cloning | MEDIUM | Drone CI | |
DR-016 |
Step image: field carries a Drone template substitution | HIGH | Drone CI | |
GCB-005 |
Build timeout unset or excessive | LOW | Cloud Build | 🔧 fix |
GCB-016 |
Step dir field contains parent-directory escape (..) | MEDIUM | Cloud Build | |
GCB-019 |
Shell entrypoint inlines a user substitution into args | HIGH | Cloud Build | |
GCB-022 |
options.substitutionOption set to ALLOW_LOOSE | LOW | Cloud Build | 🔧 fix |
GCB-023 |
Step references a user substitution not declared in substitutions: | MEDIUM | Cloud Build | |
GEM-004 |
Gemfile source URL embeds plaintext credentials | HIGH | RubyGems | |
GEM-009 |
.bundle/config committed with embedded credentials | HIGH | RubyGems | |
GHA-002 |
pull_request_target checks out PR head | CRITICAL | GitHub Actions | 🔧 fix |
GHA-009 |
workflow_run downloads upstream artifact unverified | CRITICAL | GitHub Actions | |
GHA-010 |
Local action (./path) on untrusted-trigger workflow | HIGH | GitHub Actions | |
GHA-013 |
issue_comment trigger without author guard | HIGH | GitHub Actions | |
GHA-015 |
Job has no timeout-minutes, unbounded build |
MEDIUM | GitHub Actions | 🔧 fix |
GHA-031 |
Workflow uses retired set-output / save-state command | HIGH | GitHub Actions | 🔧 fix |
GHA-032 |
run: invokes local script on untrusted-trigger workflow | CRITICAL | GitHub Actions | |
GHA-035 |
github-script step interpolates untrusted context | HIGH | GitHub Actions | |
GHA-036 |
runs-on interpolates untrusted context | HIGH | GitHub Actions | 🔧 fix |
GHA-038 |
Workflow re-enables retired ::set-env / ::add-path commands | CRITICAL | GitHub Actions | |
GHA-044 |
Build tool runs lifecycle scripts on untrusted-trigger workflow | HIGH | GitHub Actions | |
GHA-045 |
Caller-controlled ref input feeds actions/checkout | HIGH | GitHub Actions | |
GHA-046 |
Manual PR-head fetch on untrusted-trigger workflow | CRITICAL | GitHub Actions | |
GHA-053 |
if: predicate evaluates attacker-controllable context as expression | HIGH | GitHub Actions | |
GHA-058 |
Agentic CLI invoked with permission-bypass flags | HIGH | GitHub Actions | |
GHA-092 |
PR head SHA captured then re-fetched (force-push race) | HIGH | GitHub Actions | |
GL-010 |
Multi-project pipeline ingests upstream artifact unverified | CRITICAL | GitLab CI | |
GL-011 |
include: local file pulled in MR-triggered pipeline | HIGH | GitLab CI | |
GL-015 |
Job has no timeout, unbounded build |
MEDIUM | GitLab CI | 🔧 fix |
GL-032 |
tags: interpolates untrusted CI variable | HIGH | GitLab CI | 🔧 fix |
GL-033 |
Global before_script / after_script propagates taint to every job | HIGH | GitLab CI | |
HARNESS-002 |
Untrusted Harness expression interpolated into a step command | HIGH | Harness CI/CD | |
HARNESS-005 |
Step pipes a remote download into a shell interpreter | HIGH | Harness CI/CD | 🔧 fix |
HARNESS-019 |
Pipeline step lacks an explicit timeout | LOW | Harness CI/CD | |
JF-012 |
load step pulls Groovy from disk without integrity pin |
MEDIUM | Jenkins | |
JF-013 |
copyArtifacts ingests another job's output unverified | CRITICAL | Jenkins | |
JF-015 |
Pipeline has no timeout wrapper, unbounded build |
MEDIUM | Jenkins | 🔧 fix |
JF-019 |
Groovy sandbox escape pattern detected | CRITICAL | Jenkins | |
JF-032 |
Agent label interpolates attacker-controllable value | HIGH | Jenkins | 🔧 fix |
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-010 |
NuGet.config stores a feed credential in plaintext | HIGH | NuGet | |
TAINT-001 |
Untrusted input flows across step boundaries via step outputs | HIGH | GitHub Actions | |
TAINT-002 |
Untrusted input flows across jobs via jobs.<id>.outputs: |
HIGH | GitHub Actions | |
TAINT-003 |
Untrusted input forwarded into reusable workflow with: |
HIGH | GitHub Actions | |
TAINT-004 |
Untrusted input flows across jobs via dotenv artifact | HIGH | GitLab CI | |
TAINT-005 |
Untrusted input flows across steps via buildkite-agent meta-data |
HIGH | Buildkite | |
TAINT-006 |
Untrusted input flows across tasks via Tekton results |
HIGH | Tekton | |
TAINT-007 |
Untrusted input flows across templates via Argo outputs.parameters |
HIGH | Argo Workflows | |
TAINT-008 |
Untrusted input flows via GitLab extends: template inheritance |
HIGH | GitLab CI | |
TKN-003 |
Tekton param interpolated unsafely in step script | CRITICAL | Tekton | |
TKN-006 |
Tekton run lacks an explicit timeout | LOW | Tekton | |
TKN-015 |
Workspace subPath interpolates a Task parameter (path traversal) | HIGH | Tekton |
4.4.6: Rogue containers, unvetted images executed inside pipeline
Evidenced by 16 checks across 9 providers (AWS, Azure DevOps, Bitbucket, Buildkite, CircleCI, Drone CI, GitHub Actions, GitLab CI, Jenkins).
| Check | Title | Severity | Provider | Fix |
|---|---|---|---|---|
ADO-012 |
Cache@2 key derives from $(System.PullRequest.*) | MEDIUM | Azure DevOps | |
BB-018 |
Cache key derives from attacker-controllable input | MEDIUM | Bitbucket | |
BK-001 |
Buildkite plugin not pinned to an exact version | HIGH | Buildkite | |
BK-004 |
Remote script piped into shell interpreter | HIGH | Buildkite | 🔧 fix |
CB-007 |
CodeBuild webhook has no filter group | MEDIUM | AWS | |
CB-008 |
CodeBuild buildspec is inline (not sourced from a protected repo) | HIGH | AWS | |
CC-013 |
Deploy job in workflow has no branch filter | MEDIUM | CircleCI | |
CC-025 |
Cache key derives from attacker-controllable input | MEDIUM | CircleCI | |
CP-003 |
Source stage using polling instead of event-driven trigger | LOW | AWS | |
CP-007 |
CodePipeline v2 PR trigger accepts all branches | HIGH | AWS | |
DR-009 |
Cache plugin key embeds an attacker-controllable Drone variable | HIGH | Drone CI | |
GHA-011 |
Cache key derives from attacker-controllable input | MEDIUM | GitHub Actions | |
GHA-052 |
actions/cache key includes untrusted PR-controllable input | HIGH | GitHub Actions | |
GL-012 |
Cache key derives from MR-controlled CI variable | MEDIUM | GitLab CI | |
JF-003 |
Pipeline uses agent any (no executor isolation) |
MEDIUM | Jenkins | |
JF-026 |
build job: trigger ignores downstream failure |
MEDIUM | Jenkins |
This page is generated. Edit pipeline_check/core/standards/data/nist_800_190.py (mappings) or scripts/gen_standards_docs.py (intro / per-control prose) and run python scripts/gen_standards_docs.py nist_800_190.