CleanStart generates 11 cryptographic verification artifacts for every image build. These artifacts prove the image's origin, contents, and compliance. This guide walks through inspecting, understanding, and presenting each artifact to auditors or compliance teams.
The 11 Artifacts
CleanStart attaches 11 cryptographic artifacts to every OCI image (myapp:v1.2.3). These artifacts provide comprehensive verification and audit trails:
- Image Signature (Cosign) — Cryptographic proof of the image's authenticity
- SLSA Provenance Attestation — Details about the build environment and parameters
- SBOM Attestation (SPDX) — Complete software bill of materials
- Vulnerability Scan Attestation — Results from security scanning
- VEX Document (Vulnerability Exchange) — Vulnerability triage and impact assessment
- Build Log Attestation — Complete build execution history
- Configuration Attestation — Build-time configuration and parameters
- Dependency Tree Report — Detailed dependency graph
- Policy Compliance Attestation — Compliance verification results
- Code Review Attestation — Code review and approval records
- Deployment History — Deployment events and timeline
Artifact 1: Image Signature (Cosign)
Purpose: Cryptographic proof that image hasn't been tampered with since signing.
Location: Registry attachment Format: Binary signature Signed by: CI/CD build identity (service account, GitHub Actions, etc.)
Inspect
# View signature informationcosign verify \ --certificate-identity=https://github.com/org/repo/actions \ gcr.io/my-project/app:v1.2.3 # Output:# Verifying signature...# Signature verified# Subject: https://github.com/org/repo/actions# Certificate: CN=https://github.com/org/repo/actions# Issuer: Fulcio (OIDC issuer)# Certificate validity: 2024-03-20 to 2024-03-21 # Get signature detailscosign verify --certificate-identity=... \ gcr.io/my-project/app:v1.2.3 \ --certificate-github-workflow-ref=refs/heads/main \ --certificate-github-workflow-trigger=pushVerify Manually
# Check signature was created by GitHub Actionscosign verify \ --certificate-identity=https://token.actions.githubusercontent.com \ --certificate-oidc-issuer=https://token.actions.githubusercontent.com \ gcr.io/my-project/app:v1.2.3 # Check signature was created for specific branchcosign verify \ --certificate-github-workflow-ref=refs/heads/main \ gcr.io/my-project/app:v1.2.3For Auditors
"This image signature proves it was built and signed by our CI/CD pipeline on main branch. The certificate is signed by Fulcio (OIDC issuer), proving the signer's identity."
Artifact 2: SLSA Provenance Attestation
Purpose: Cryptographic proof of build environment, build parameters, and source commit.
Location: Registry (cosign attestation) Format: In-toto SLSA v0.2 JSON Signed by: Build service account
Inspect
# View SLSA provenancecosign verify-attestation \ --type slsa \ --certificate-identity=... \ gcr.io/my-project/app:v1.2.3 | jq '.payload | @base64d | fromjson' # Output:# {# "predicateType": "https://slsa.dev/provenance/v0.2",# "predicate": {# "builder": {# "id": "https://github.com/org/repo/actions/workflows/build.yml"# },# "sourceRepository": "https://github.com/org/repo",# "ref": "refs/heads/main",# "commit": "abc123def456...",# "buildStartedOn": "2024-03-20T10:00:00Z",# "buildFinishedOn": "2024-03-20T10:05:30Z",# "completeness": {# "arguments": true,# "environment": true,# "materials": true# },# "reproducible": true,# "materials": [# {# "uri": "git+https://github.com/org/repo@abc123",# "digest": {# "sha256": "..."# }# }# ]# }# }Verify
# Confirm build came from main branchcosign verify-attestation --type slsa \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .predicate.ref'# Output: refs/heads/main # Confirm source commitcosine verify-attestation --type slsa \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .predicate.commit' # Verify build completed successfullycosign verify-attestation --type slsa \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .predicate.buildFinishedOn'For Auditors
"SLSA provenance proves this image was built from commit ABC123 on main branch, built in GitHub Actions from start to finish, with all arguments and environment captured."
Artifact 3: SBOM Attestation (SPDX 3.0)
Purpose: Complete inventory of all software components in the image.
Location: Registry (cosign attestation) Format: SPDX 3.0 JSON (machine-readable) Contains: All packages, versions, licenses, sources
Inspect
# View SBOMcosign verify-attestation \ --type sbom \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d' # Pretty-print SPDXcosign verify-attestation --type sbom \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .' > sbom.spdx.json # View summaryjq '.packages | length' sbom.spdx.json# Output: 247 packages total # List all packagesjq '.packages[] | {name: .name, version: .versionInfo, license: .licenseConcluded}' \ sbom.spdx.json | head -20 # Find specific packagejq '.packages[] | select(.name=="golang.org/x/crypto")' sbom.spdx.jsonVerify
# Validate SBOM formatjq '.spdxVersion, .dataLicense, .packages | length' sbom.spdx.json# Output: SPDX-3.0, CC0-1.0, 247 # Check for FIPS compliancejq '.packages[] | select(.versionInfo | contains("md5"))' sbom.spdx.json# Empty = no MD5 packages (FIPS compliant) # List all licenses usedjq '.packages[].licenseConcluded' sbom.spdx.json | sort | uniqFor Auditors
"The SBOM lists all 247 software components in this image, including versions and licenses. No FIPS-forbidden algorithms or packages detected. Scan for license compliance shows all approved open-source licenses."
Artifact 4: Vulnerability Scan Attestation
Purpose: Proof that image was scanned and passed vulnerability checks.
Location: Registry (cosign attestation) Format: Vulnerability report JSON Contains: CVE count by severity, scan timestamp
Inspect
# View vulnerability scancosign verify-attestation \ --type vuln \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson' # Output:# {# "scanTime": "2024-03-20T10:06:00Z",# "scanner": "trivy/0.46.0",# "results": {# "critical": 0,# "high": 2,# "medium": 8,# "low": 15,# "unknown": 0# },# "findingDetails": [# {# "cveId": "CVE-2024-1234",# "severity": "HIGH",# "package": "openssl",# "version": "3.0.7",# "status": "fixed_in_version=3.1.0"# }# ]# }Verify
# Check no critical vulnerabilitiescosign verify-attestation --type vuln \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .results.critical'# Output: 0 # List vulnerabilities with statuscosign verify-attestation --type vuln \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .findingDetails[] | {cve: .cveId, severity: .severity, package: .package, status: .status}' # Confirm scan was recent (within last 24 hours)cosign verify-attestation --type vuln \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .scanTime' | \ xargs -I {} date -d {} +%s # Convert to Unix timestamp for age checkFor Auditors
"Vulnerability scan completed 2024-03-20 shows 0 critical, 2 high (both with patches available), 8 medium. No vulnerabilities blocking deployment."
Artifact 5: VEX Document (Vulnerability Exchange)
Purpose: Triage information for vulnerabilities (status, justification, mitigations).
Location: Registry (cosign attestation) or alongside SBOM Format: SPDX VEX JSON Contains: Status of each CVE (affected, unaffected, fixed, etc.)
Inspect
# View VEX documentcosign verify-attestation \ --type vex \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson' # Output:# {# "bomRef": "pkg:docker/myapp@v1.2.3",# "vulnerabilities": [# {# "ref": "CVE-2024-1234",# "status": "affected",# "justification": null,# "impact": "HIGH",# "statement": "Fixed in next release (v1.2.4) scheduled for March 25"# },# {# "ref": "CVE-2024-5678",# "status": "unaffected",# "justification": "component_not_present",# "statement": "Tool is never invoked with untrusted input"# }# ]# }Verify
# Find all unaffected CVEs (with justification)cosign verify-attestation --type vex \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .vulnerabilities[] | select(.status == "unaffected")' # Count status breakdowncosign verify-attestation --type vex \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .vulnerabilities | group_by(.status) | map({status: .[0].status, count: length})' # Output:# [# {"status": "affected", "count": 2},# {"status": "fixed", "count": 5},# {"status": "unaffected", "count": 10}# ]For Auditors
"VEX document provides triage details: 2 CVEs are affected (patches available), 5 are fixed in newer dependencies, 10 are unaffected (tools not invoked or not used in deployment context)."
Artifact 6: Build Log Attestation
Purpose: Complete CI/CD build execution log (for forensics and compliance).
Location: Registry (cosign attestation) or artifact storage Format: Structured build log (JSONL) Contains: Every step, every output, execution times
Inspect
# View build logcosign verify-attestation \ --type buildlog \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson' # Output (excerpt):# {# "steps": [# {"time": "2024-03-20T10:00:00Z", "step": "Checkout code", "duration": "2s"},# {"time": "2024-03-20T10:00:02Z", "step": "Run SAST", "output": "No issues", "duration": "45s"},# {"time": "2024-03-20T10:00:47Z", "step": "Build image", "duration": "180s"},# {"time": "2024-03-20T10:03:47Z", "step": "Run tests", "output": "247 tests passed", "duration": "32s"},# {"time": "2024-03-20T10:04:19Z", "step": "Sign image", "duration": "5s"},# {"time": "2024-03-20T10:04:24Z", "step": "Push to registry", "duration": "12s"}# ],# "totalTime": "327s"# }For Auditors
"Build log proves image went through full pipeline: source analysis → build → testing → signing → registry push, with all steps successful and timestamped."
Artifact 7: Configuration Attestation
Purpose: Proof of which configuration was applied during build.
Location: Registry (cosign attestation) Format: JSON (environment variables, build flags, etc.) Contains: Build parameters, flags, settings
Inspect
# View build configurationcosign verify-attestation \ --type config \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson' # Output:# {# "buildArgs": {# "BASE_IMAGE": "cleanstart/gcc:14-prod",# "FIPS_MODE": "enabled",# "STRIP_BINARIES": "true"# },# "buildEnv": {# "DOCKER_BUILDKIT": "1",# "BUILDKIT_CONTEXT_KEEP_GIT_DIR": "1"# },# "target": "prod" # Multi-stage: which stage was final# }For Auditors
"Configuration proves image used cleanstart/gcc:14-prod base, FIPS mode enabled, and 'prod' target (not 'dev')."
Artifact 8: Dependency Tree Report
Purpose: Transitive dependency graph (what depends on what).
Location: Artifact storage (JSON file) Format: Hierarchical dependency graph Contains: Direct and transitive dependencies
Inspect
# View dependency treegsutil cat gs://my-audit-logs/app-v1.2.3-deps.json | jq '.' # Output (excerpt):# {# "app": {# "version": "1.2.3",# "dependencies": {# "express": {# "version": "4.18.2",# "dependencies": {# "body-parser": {"version": "1.20.1"},# "cookie": {"version": "0.5.0"}# }# },# "pg": {# "version": "8.10.0"# }# }# }# }For Auditors
"Dependency tree shows app depends on express (4.18.2) and pg (8.10.0), with transitive dependencies on body-parser and cookie."
Artifact 9: Policy Compliance Attestation
Purpose: Proof that image was checked against security policy and passed.
Location: Registry (cosign attestation) Format: Compliance check results (JSON) Contains: Policy checks, pass/fail status, exemptions
Inspect
# View policy compliancecosign verify-attestation \ --type policy \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson' # Output:# {# "policyName": "Production Security Policy",# "policyVersion": "2.1",# "checkResults": {# "fips_compliance": {"status": "pass"},# "stig_baseline": {"status": "pass"},# "non_root_user": {"status": "pass", "value": "uid=65532"},# "capabilities_dropped": {"status": "pass"},# "readonly_filesystem": {"status": "pass"},# "network_policies": {"status": "pass"},# "resource_limits": {"status": "pass"},# "image_signed": {"status": "pass"},# "sbom_present": {"status": "pass"}# },# "overallStatus": "PASS",# "checkedAt": "2024-03-20T10:06:15Z"# }Verify
# Check all policies passedcosign verify-attestation --type policy \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .checkResults[] | select(.status != "pass")'# Empty = all checks passed # List failed checks (if any)cosign verify-attestation --type policy \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .checkResults | to_entries[] | select(.value.status == "fail")'For Auditors
"Policy compliance check passed all 9 security requirements: FIPS enabled, STIG baseline met, non-root user, all Linux capabilities dropped, read-only filesystem, etc."
Artifact 10: Code Review Attestation
Purpose: Proof that pull request was reviewed and approved before merge.
Location: Registry (cosign attestation) Format: GitHub/GitLab review metadata (JSON) Contains: Reviewers, approval status, review comments
Inspect
# View code review attestationcosign verify-attestation \ --type review \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson' # Output:# {# "pullRequest": "https://github.com/org/repo/pull/1234",# "sourceCommit": "abc123def456...",# "reviews": [# {# "reviewer": "alice@example.com",# "approval": "approved",# "timestamp": "2024-03-20T09:30:00Z",# "comment": "Code looks good, security checks passed"# },# {# "reviewer": "bob@example.com",# "approval": "approved",# "timestamp": "2024-03-20T09:45:00Z",# "comment": "LGTM - verified test coverage increased"# }# ],# "requiredReviewsCount": 2,# "approvalsCount": 2# }Verify
# Check minimum approvals metcosign verify-attestation --type review \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | select(.approvalsCount >= .requiredReviewsCount) | "Approval requirement met"' # List reviewerscosign verify-attestation --type review \ gcr.io/my-project/app:v1.2.3 | \ jq '.payload | @base64d | fromjson | .reviews[].reviewer'For Auditors
"Code review attestation proves PR #1234 was reviewed and approved by Alice and Bob before merge to main."
Artifact 11: Deployment History
Purpose: Audit trail of where/when image was deployed.
Location: Artifact storage (deployment events) Format: Deployment log (JSON) Contains: Deployment locations, timestamps, rollouts, rollbacks
Inspect
# View deployment historygsutil cat gs://my-audit-logs/app-v1.2.3-deployments.json | jq '.[]' # Output:# [# {# "environment": "staging",# "deployedAt": "2024-03-20T10:30:00Z",# "cluster": "gke-staging",# "namespace": "staging",# "replicas": 2,# "status": "success"# },# {# "environment": "production",# "deployedAt": "2024-03-20T14:00:00Z",# "cluster": "gke-prod-us-central1",# "namespace": "production",# "replicas": 5,# "status": "success"# }# ]For Auditors
"Deployment history shows image v1.2.3 deployed to staging at 10:30 UTC, then to production at 14:00 UTC, both successful."
Complete Verification Walk-Through
For Compliance Review
#!/bin/bash IMAGE="gcr.io/my-project/app:v1.2.3" echo "=== Image Verification Artifacts ===" echo -e "\n1. Signature:"cosign verify --certificate-identity=... $IMAGE echo -e "\n2. SLSA Provenance:"cosign verify-attestation --type slsa $IMAGE | jq '.payload | @base64d | fromjson | .predicate | {builder, ref, commit}' echo -e "\n3. SBOM Summary:"cosign verify-attestation --type sbom $IMAGE | jq '.payload | @base64d | fromjson | {packages: (.packages | length), licenses: (.packages[].licenseConcluded | unique)}' echo -e "\n4. Vulnerability Status:"cosign verify-attestation --type vuln $IMAGE | jq '.payload | @base64d | fromjson | .results' echo -e "\n5. Policy Compliance:"cosign verify-attestation --type policy $IMAGE | jq '.payload | @base64d | fromjson | {status: .overallStatus, checks: (.checkResults | to_entries | length)}' echo -e "\n6. Code Review:"cosign verify-attestation --type review $IMAGE | jq '.payload | @base64d | fromjson | {pr: .pullRequest, approvals: .approvalsCount}' echo -e "\n=== Verification Complete ==="Presenting Artifacts to Auditors
Sample Audit Report
SECURITY AUDIT REPORT: myapp v1.2.3Generated: 2024-03-20 SUPPLY CHAIN VERIFICATION:Image Signature: Signed by GitHub Actions (main branch) - VERIFIEDBuild Provenance: SLSA v0.2, commit abc123, 2024-03-20 10:00-10:05 UTC - VERIFIEDCode Review: 2 approvals (alice@example.com, bob@example.com) - VERIFIED CONTENTS VERIFICATION:SBOM: 247 packages, all with identified licenses - VERIFIEDVulnerabilities: 0 critical, 2 high (patches available), 8 medium - VERIFIEDVEX Triage: 10 unaffected CVEs, 5 fixed in newer versions - VERIFIED COMPLIANCE VERIFICATION:FIPS Mode: Enabled, no non-FIPS algorithms - VERIFIEDSTIG Baseline: All 9 requirements passed - VERIFIEDSecurity Context: Non-root (UID 65532), all capabilities dropped - VERIFIEDPolicy Compliance: Production Security Policy v2.1 passed - VERIFIED OPERATIONAL VERIFICATION:Build Log: All steps successful, total build time 327 seconds - VERIFIEDDeployment History: Deployed to staging 10:30 UTC, production 14:00 UTC - VERIFIEDAttestation Integrity: All artifacts signed and verified - VERIFIED OVERALL ASSESSMENT: APPROVED FOR PRODUCTIONRisk Level: LOWApproval: Security TeamDate: 2024-03-20