The Validate Gateway is an automated security checkpoint that runs before pushing to registry—it verifies FIPS compliance, STIG baseline requirements, and security hardening. Non-compliant configurations are blocked with clear remediation steps, preventing insecure images from reaching production. It works like linting for security compliance, catching configuration errors early.
The following diagram illustrates the validation gateway flow from local build through compliance checks to registry push:
graph TD A["Local Docker<br/>Build"] -->|Input| B["Validate Gateway<br/>Checkpoint"] B -->|Check 1| C["FIPS Algorithm<br/>Verification"] C -->|Scan| D["Cryptographic<br/>Binaries"] D -->|Result| E{FIPS<br/>Compliant?} E -->|No| F["FAIL:<br/>Non-FIPS Algo"] F -->|Report| G["Blocked<br/>with Remediation"] E -->|Yes| H["Check 2:<br/>STIG Baseline"] H -->|Verify| I["Non-root User<br/>Capabilities<br/>Read-only FS"] I -->|Result| J{STIG<br/>Compliant?} J -->|No| K["FAIL:<br/>Hardening Issues"] K -->|Report| G J -->|Yes| L["Check 3:<br/>Security<br/>Context"] L -->|Verify| M["Image<br/>Signature<br/>Network Policy"] M -->|Result| N{Context<br/>Valid?} N -->|No| O["FAIL:<br/>Security Issues"] O -->|Report| G N -->|Yes| P["Check 4:<br/>Vulnerability<br/>Scan"] P -->|Scan| Q["CVE<br/>Database"] Q -->|Result| R{Scan<br/>Clean?} R -->|No| S["FAIL:<br/>CVEs Found"] S -->|Report| G R -->|Yes| T["All Checks<br/>PASS"] T -->|Authorize| U["Push to<br/>Registry"] U -->|Complete| V["Secure Image<br/>Deployed"] G -->|Fix Issues| A style C fill:#ccffcc style H fill:#ccffcc style L fill:#ccffcc style P fill:#ccffcc style T fill:#99ff99 style G fill:#ffccccArchitecture
The Validate Gateway operates as an automated security checkpoint in your build pipeline. The process begins with a local Docker build using docker build .... Once the image is built, it flows into the Validate Gateway check, which performs five critical verification steps: FIPS algorithm compliance, STIG baseline hardening, container security context validation, cryptographic attestations, and image vulnerability scanning.
Based on the results of these checks, the workflow branches into two paths. If all checks pass, the image is authorized to push to the registry. If any check fails, the gateway blocks the push and generates a detailed report with specific remediation steps, allowing developers to fix the issues and rebuild.
Compliance Checks
1. FIPS Algorithm Verification
Blocked algorithms: MD5, MD4, RIPEMD SHA1 (except in HMAC for backward compatibility) DES, 3DES, RC4, Blowfish Camellia (non-standard). Allowed algorithms: HMAC-SHA256, HMAC-SHA384, HMAC-SHA512 AES-128-GCM, AES-256-GCM, AES-256-CBC ECDSA, RSA-2048+ SHA256, SHA384, SHA512. Example validation:
# Check image for FIPS violationsvalidate-gateway check \ --image gcr.io/my-project/app:latest \ --fips-mode strict # Output:# PASS: No non-FIPS algorithms detected in image2. STIG Baseline Requirements
Checked requirements: Non-root user (UID ≥ 1000, but not 0) Linux capabilities dropped to minimum Read-only root filesystem where possible Network policies configured Resource limits defined Liveness/readiness probes configured Security context hardened Image signed with valid certificate. Example validation:
validate-gateway check \ --image gcr.io/my-project/app:latest \ --stig-baseline # Output:# Non-root user (UID 65532) - PASS# Capabilities dropped: NET_ADMIN, SYS_ADMIN - PASS# Read-only root filesystem - PASS# Network policies missing - FAIL# Resource limits missing - FAIL3. Container Security Context
Verified: runAsNonRoot: true allowPrivilegeEscalation: false capabilities: drop: [ALL] readOnlyRootFilesystem: true. Example validation:
validate-gateway check \ --kubernetes-manifest deployment.yaml \ --security-context strict # Output:# Checking securityContext in deployment.yaml...# Container running as non-root (UID 65532) - PASS# readOnlyRootFilesystem: false - FAIL# allowPrivilegeEscalation: not set - FAIL4. Attestation Requirements
Checked: Image signature present SLSA provenance attestation attached SBOM (SPDX) attestation present Vulnerability scan attestation exists. Example validation:
validate-gateway check \ --image gcr.io/my-project/app:latest \ --require-attestations sbom,slsa,scan # Output:# Image signature valid - PASS# SLSA provenance missing - FAIL# SBOM present - PASS# Vulnerability scan attached - PASS5. Vulnerability Scanning
Failure conditions: Critical vulnerabilities found High-severity vulnerabilities > threshold (default: 3) Medium-severity vulnerabilities > threshold (default: 10) Vulnerable base image (non-CleanStart). Example validation:
validate-gateway check \ --image gcr.io/my-project/app:latest \ --max-critical 0 \ --max-high 3 \ --max-medium 10 # Output:# Scanning for vulnerabilities...# Critical: 0# High: 2 (within threshold of 3) - PASS# Medium: 8 (within threshold of 10) - PASS# Result: PASSConfiguration Files
validate-gateway.yaml (Global Policy)
version: "1.0"name: "Production Security Policy" # FIPS compliancefips: enabled: true mode: strict # or: compatible allowed_algorithms: - HMAC-SHA256 - HMAC-SHA384 - AES-256-GCM - ECDSA forbidden_algorithms: - MD5 - SHA1 - DES - RC4 # STIG baselinestig: enabled: true baseline: dod-5220.22-m # or: rhel-8, centos-7 requirements: - non_root_user - capabilities_dropped - readonly_filesystem - network_policies - resource_limits - security_context # Container securitysecurity_context: require_non_root: true require_dropped_capabilities: - NET_ADMIN - SYS_ADMIN - SYS_PTRACE require_readonly_filesystem: true require_no_privilege_escalation: true # Attestationsattestations: required: - signature - sbom - slsa_provenance - vulnerability_scan signature_algorithm: rsa-4096 certificate_validity_days: 365 # Vulnerability scanningvulnerabilities: scan_enabled: true max_critical: 0 max_high: 3 max_medium: 10 max_low: 50 ignore_cvess: [] # CVEs to ignore (with justification) # Base image requirementsbase_images: allowed_registries: - cleanstart - bitnami # allowed but warns blocked_registries: - docker.io # No unvetted images require_signed: true # Manifest validation (Kubernetes)kubernetes: require_resources: true require_probes: true require_security_context: true require_non_root_user: true.clnstrt-validate (Local Override)
# Override global policy for specific projectfips: mode: compatible # Less strict for legacy app vulnerabilities: ignore_cvess: - CVE-2024-1234 # Justification: Unfixable, mitigation in place - CVE-2024-5678 # Justification: Upstream patched in next release # Skip certain checks for specific buildsskip_checks: - readonly_filesystem # We need writable /tmp - network_policies # Legacy project, will add laterUsing Validate Gateway
1. Pre-Push Check (Local Development)
# Check image locally before pushingvalidate-gateway check \ --image myapp:latest \ --policy ./validate-gateway.yaml # Verbose outputvalidate-gateway check \ --image myapp:latest \ --policy ./validate-gateway.yaml \ --verbose # Output example:## Validate Gateway Security Check for myapp:latest# Policy: Production Security Policy## FIPS Compliance: No non-FIPS algorithms detected# STIG Baseline Assessment:# - Non-root user (UID 65532): PASS# - Capabilities dropped: PASS# - Read-only filesystem: FAIL# → Fix: Add readOnlyRootFilesystem: true to securityContext# Network policies configured - PASS# Resource limits defined - PASS# Attestations:# Image signed with Cosign - PASS# SLSA provenance attached - PASS# SBOM present (SPDX 3.0) - PASS# Vulnerabilities:# • Critical: 0# • High: 2 / 3 allowed# • Medium: 8 / 10 allowed# Base Image:# cleanstart/gcc:14-prod (approved)# ────────────────────────────────────────# Result: FAIL (1 blocking issue)# Status: Cannot push until fixed2. Fix Issues
# Before (FAILS validate-gateway)FROM cleanstart-gcc:14-prodUSER 65532ENTRYPOINT ["/usr/local/bin/app"] # After (PASSES validate-gateway)FROM cleanstart-gcc:14-prodUSER 65532ENTRYPOINT ["/usr/local/bin/app"] # Add missing security contextsecurityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: - ALL3. CI/CD Integration
GitHub Actions:
- name: Validate Gateway Pre-Push Check run: | validate-gateway check \ --image $DOCKER_IMAGE:${{ github.sha }} \ --policy ./validate-gateway.yaml \ --fail-on-warning # Blocks push if validation failsGitLab CI:
validate_gateway: stage: verify script: - validate-gateway check --image $DOCKER_IMAGE:$CI_COMMIT_SHA --policy ./validate-gateway.yaml # Pipeline stops if check failsGoogle Cloud Build:
steps: - name: 'Validate Gateway Check' args: - 'validate-gateway' - 'check' - '--image' - 'us-docker.pkg.dev/${PROJECT_ID}/prod/myapp:${SHORT_SHA}' - '--policy' - './validate-gateway.yaml' # Build fails if validation fails4. Bypass Procedures (Exceptions)
For rare cases requiring exceptions:
# Generate exception requestvalidate-gateway request-exception \ --check readonly_filesystem \ --image myapp:latest \ --justification "App requires /tmp for temp file processing" \ --duration 30d # Request valid for 30 days # Output: exception-request-123.yaml (needs approval)Exception approval:
apiVersion: cleanstart.dev/v1kind: ValidationExceptionmetadata: name: exception-123 approver: security-team@example.comspec: check: readonly_filesystem image: myapp:* justification: "App requires /tmp for temp file processing" approved: true validUntil: "2024-04-20T00:00:00Z" approvedBy: name: security-team timestamp: "2024-03-20T10:00:00Z"Policy Templates
Strict Production Policy
# Maximum security for critical production systemsvalidate-gateway.yaml: | fips: mode: strict stig: baseline: dod-5220.22-m security_context: require_readonly_filesystem: true vulnerabilities: max_critical: 0 max_high: 0 max_medium: 3 attestations: required: [signature, sbom, slsa_provenance, vulnerability_scan]Standard Production Policy
# Balanced security for typical production appsfips: mode: strictstig: baseline: rhel-8vulnerabilities: max_critical: 0 max_high: 3 max_medium: 10attestations: required: [signature, sbom]Development Policy
# Relaxed for development/testingfips: mode: compatiblevulnerabilities: max_critical: 5 max_high: 10 max_medium: 50attestations: required: [sbom] # Just SBOMskip_checks: - readonly_filesystem # OK for dev - network_policies # OK for devMonitoring and Reporting
Check Results Dashboard
# View check historyvalidate-gateway history \ --days 30 \ --project myapp # Output:# Date Image Policy Status Issues# 2024-03-20 myapp:v1.2.3-pr42 Dev PASS 0# 2024-03-20 myapp:v1.2.3-rc1 Prod FAIL 2 (fips, attestations)# 2024-03-19 myapp:v1.2.2 Prod PASS 0# 2024-03-18 myapp:v1.2.1 Prod PASS 0Generate Compliance Report
validate-gateway report \ --days 30 \ --policy ./validate-gateway.yaml \ --format pdf \ --output compliance-report-march.pdf # Report includes:# - Pass/fail summary# - Trend analysis# - Exception justifications# - Remediation trackingTroubleshooting
Check Fails: "FIPS algorithms detected"
# Find which file contains the violationvalidate-gateway check \ --image myapp:latest \ --verbose # Look for file path in output# Example: "SHA1 detected in /usr/local/lib/libcrypto.so" # Solution: Rebuild image without non-FIPS dependencies# Or request FIPS exception (rarely approved)Check Fails: "readOnlyRootFilesystem not set"
# Add security context to pod specsecurityContext: readOnlyRootFilesystem: true # If app needs writable directories:volumeMounts: - name: tmp mountPath: /tmp - name: logs mountPath: /var/log volumes: - name: tmp emptyDir: {} - name: logs emptyDir: {}Check Fails: "Image not signed"
# Sign image with clnstrt-cliclnstrt-cli sign \ --image myapp:latest \ --key cosign.key # Or use Cloud KMSclnstrt-cli sign \ --image myapp:latest \ --key kms://projects/PROJECT_ID/locations/us-central1/keyRings/cosign-keys/cryptoKeys/prodCheck Fails: "Vulnerability exceeds threshold"
# View detailed vulnerability reportvalidate-gateway check \ --image myapp:latest \ --verbose \ --show-vulnerabilities # For each CVE, either:# 1. Update base image to patched version# 2. Request CVE exception (needs justification)# 3. Deploy mitigation (WAF rule, etc.)