Skip to main content
CleanStart

Knowledge Hub

Pre-Build Security Compliance Gates with Validate Gateway

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:#ffcccc

Architecture

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 image

2. 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 - FAIL

3. 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 - FAIL

4. 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 - PASS

5. 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: PASS

Configuration 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 later

Using 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 fixed

2. 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:      - ALL

3. 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 fails

GitLab CI:

validate_gateway:  stage: verify  script:    - validate-gateway check        --image $DOCKER_IMAGE:$CI_COMMIT_SHA        --policy ./validate-gateway.yaml    # Pipeline stops if check fails

Google 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 fails

4. 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 dev

Monitoring 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    0

Generate 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 tracking

Troubleshooting

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/prod

Check 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.)