What it does. Implements supply chain integrity verification for container builds with the in-toto framework: generating signing keys, defining a supply chain layout, recording pipeline steps as signed link metadata, verifying before deployment, enforcing at Kubernetes admission, and integrating with SLSA. Use when attesting CI/CD pipeline steps, proving an image followed the approved build process, or enforcing provenance at admission. Keywords: in-toto, layout, link metadata, step, inspection, SLSA, provenance, admission. Do not use for signing and verifying images with Cosign - use implementing-image-provenance-verification-with-cosign. Part of mukul975/Anthropic-Cybersecurity-Skills (817 security skills) (mukul975/Anthropic-Cybersecurity-Skills).
Install
npx skills add mukul975/Anthropic-Cybersecurity-Skills --skill implementing-supply-chain-security-with-in-toto, or copy the skill folder into ~/.claude/skills/implementing-supply-chain-security-with-in-toto/.
- Raw file:
curl -sL https://raw.githubusercontent.com/mukul975/Anthropic-Cybersecurity-Skills/HEAD/skills/implementing-supply-chain-security-with-in-toto/SKILL.md
SKILL.md (verbatim)
name: implementing-supply-chain-security-with-in-toto
description: >-
Implements supply chain integrity verification for container builds with the in-toto
framework: generating signing keys, defining a supply chain layout, recording pipeline steps
as signed link metadata, verifying before deployment, enforcing at Kubernetes admission, and
integrating with SLSA. Use when attesting CI/CD pipeline steps, proving an image followed
the approved build process, or enforcing provenance at admission. Keywords: in-toto, layout,
link metadata, step, inspection, SLSA, provenance, admission. Do not use for signing and
verifying images with Cosign - use implementing-image-provenance-verification-with-cosign.
domain: cybersecurity
subdomain: container-security
tags:
- in-toto
- supply-chain-security
- attestation
- slsa
- sigstore
- container-security
- cncf
- provenance
- sbom
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- PR.PS-01
- PR.IR-01
- ID.AM-08
- DE.CM-01
mitre_attack:
- T1610
- T1611
- T1609
- T1525
- T1195
Implementing Supply Chain Security with in-toto
Overview
in-toto is a CNCF graduated project that ensures the integrity of software supply chains from initiation to end-user installation. It creates a verifiable record of the entire software development lifecycle by generating cryptographically signed attestations (called "link metadata") at each step, proving what happened, who performed it, and what artifacts were produced. For container environments, in-toto verifies that images deployed to Kubernetes followed approved build processes and have not been tampered with.
When to Use
- When deploying or configuring implementing supply chain security with in toto capabilities in your environment
- When establishing security controls aligned to compliance requirements
- When building or improving security architecture for this domain
- When conducting security assessments that require this implementation
Prerequisites
- Python 3.8+ or Go runtime for in-toto client libraries
- GPG or Ed25519 keys for signing attestations
- Container build pipeline (Docker, Buildah, or Kaniko)
- Container registry (Docker Hub, ECR, GCR, or Harbor)
- Kubernetes cluster for deployment verification
Core Concepts
Supply Chain Layout
The layout is the central policy document that defines:
- Steps: Ordered operations in the supply chain (clone, build, test, package, push)
- Functionaries: Authorized entities (people or CI systems) that perform each step
- Inspections: Client-side verification checks performed at verification time
- Expected artifacts: Input/output relationships between steps
from in_toto.models.layout import Layout, Step, Inspection
from securesystemslib.interface import import_ed25519_privatekey_from_file
# Create the supply chain layout
layout = Layout()
layout.set_relative_expiration(months=3)
# Define the code clone step
step_clone = Step(name="clone")
step_clone.expected_materials = []
step_clone.expected_products = [["CREATE", "src/*"]]
step_clone.pubkeys = [clone_functionary_keyid]
step_clone.expected_command = ["git", "clone"]
step_clone.threshold = 1
# Define the build step
step_build = Step(name="build")
step_build.expected_materials = [["MATCH", "src/*", "WITH", "PRODUCTS", "FROM", "clone"]]
step_build.expected_products = [["CREATE", "image.tar"]]
step_build.pubkeys = [build_functionary_keyid]
step_build.expected_command = ["docker", "build"]
step_build.threshold = 1
# Define the scan step
step_scan = Step(name="scan")
step_scan.expected_materials = [["MATCH", "image.tar", "WITH", "PRODUCTS", "FROM", "build"]]
step_scan.expected_products = [["CREATE", "scan-report.json"]]
step_scan.pubkeys = [scan_functionary_keyid]
step_scan.threshold = 1
layout.steps = [step_clone, step_build, step_scan]
Each step execution generates a link file containing:
- Materials consumed (input artifacts with hashes)
- Products created (output artifacts with hashes)
- Command executed
- Cryptographic signature of the functionary
Verification Process
At deployment time, the verifier checks:
- All required steps were performed
- Each step was signed by an authorized functionary
- Artifact hashes chain correctly between steps
- No unauthorized modifications occurred between steps
Implementation
Step 1: Generate Signing Keys
# Generate Ed25519 key pairs for each functionary
mkdir -p keys
# Project owner key (signs the layout)
in-toto-keygen --type ed25519 keys/owner
# CI builder key
in-toto-keygen --type ed25519 keys/builder
# Security scanner key
in-toto-keygen --type ed25519 keys/scanner
Step 2: Create the Supply Chain Layout
#!/usr/bin/env python3
"""Generate in-toto supply chain layout for container builds."""
from in_toto.models.layout import Layout, Step, Inspection
from in_toto.models.metadata import Envelope
from securesystemslib.signer import CryptoSigner
from securesystemslib.interface import import_ed25519_publickey_from_file
def create_container_build_layout():
layout = Layout()
layout.set_relative_expiration(months=6)
# Load functionary public keys
builder_key = import_ed25519_publickey_from_file("keys/builder.pub")
scanner_key = import_ed25519_publickey_from_file("keys/scanner.pub")
layout.keys = {
builder_key["keyid"]: builder_key,
scanner_key["keyid"]: scanner_key,
}
# Step 1: Source code checkout
checkout = Step(name="checkout")
checkout.expected_materials = []
checkout.expected_products = [
["CREATE", "Dockerfile"],
["CREATE", "src/*"],
["CREATE", "requirements.txt"],
]
checkout.pubkeys = [builder_key["keyid"]]
checkout.threshold = 1
# Step 2: Build container image
build = Step(name="build")
build.expected_materials = [
["MATCH", "Dockerfile", "WITH", "PRODUCTS", "FROM", "checkout"],
["MATCH", "src/*", "WITH", "PRODUCTS", "FROM", "checkout"],
]
build.expected_products = [["CREATE", "image-digest.txt"]]
build.pubkeys = [builder_key["keyid"]]
build.threshold = 1
# Step 3: Security scan
scan = Step(name="scan")
scan.expected_materials = [
["MATCH", "image-digest.txt", "WITH", "PRODUCTS", "FROM", "build"]
]
scan.expected_products = [
["CREATE", "vulnerability-report.json"],
["CREATE", "sbom.json"],
]
scan.pubkeys = [scanner_key["keyid"]]
scan.threshold = 1
# Inspection: Verify no critical vulnerabilities
inspect_vulns = Inspection(name="verify-no-critical-vulns")
inspect_vulns.expected_materials = [
["MATCH", "vulnerability-report.json", "WITH", "PRODUCTS", "FROM", "scan"]
]
inspect_vulns.run = [
"python", "-c",
"import json,sys; r=json.load(open('vulnerability-report.json')); "
"sys.exit(1) if any(v['severity']=='CRITICAL' for v in r.get('vulnerabilities',[])) else sys.exit(0)"
]
layout.steps = [checkout, build, scan]
layout.inspect = [inspect_vulns]
return layout
if __name__ == "__main__":
layout = create_container_build_layout()
# Sign with owner key and save
owner_signer = CryptoSigner.from_priv_key_uri("file:keys/owner")
envelope = Envelope.from_signable(layout)
envelope.create_signature(owner_signer)
envelope.dump("root.layout")
print("Layout created and signed: root.layout")
Step 3: Record Pipeline Steps
# In CI/CD pipeline - record each step
# Step 1: Checkout
in-toto-run --step-name checkout \
--key keys/builder \
--products Dockerfile src/* requirements.txt \
-- git clone https://github.com/org/app.git .
# Step 2: Build
in-toto-run --step-name build \
--key keys/builder \
--materials Dockerfile src/* \
--products image-digest.txt \
-- bash -c "docker build -t app:latest . && docker inspect --format='{{.Id}}' app:latest > image-digest.txt"
# Step 3: Scan
in-toto-run --step-name scan \
--key keys/scanner \
--materials image-digest.txt \
--products vulnerability-report.json sbom.json \
-- bash -c "trivy image --format json app:latest > vulnerability-report.json && syft app:latest -o json > sbom.json"
Step 4: Verify Before Deployment
# Verify the entire supply chain
in-toto-verify --layout root.layout \
--layout-key keys/owner.pub \
--link-dir ./link-metadata/
# If verification passes, proceed with deployment
if [ $? -eq 0 ]; then
kubectl apply -f deployment.yaml
echo "Supply chain verification passed - deploying"
else
echo "SUPPLY CHAIN VERIFICATION FAILED - blocking deployment"
exit 1
fi
Step 5: Kubernetes Admission Control
Integrate with a policy engine to verify attestations at admission:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: in-toto-verifier
webhooks:
- name: verify.in-toto.io
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
operations: ["CREATE", "UPDATE"]
clientConfig:
service:
name: in-toto-webhook
namespace: security
path: /verify
failurePolicy: Fail
sideEffects: None
admissionReviewVersions: ["v1"]
SLSA Integration
in-toto attestations map directly to SLSA (Supply chain Levels for Software Artifacts) requirements:
| SLSA Level |
in-toto Requirement |
| Level 1 |
Build process documented (layout exists) |
| Level 2 |
Signed attestations from hosted build service |
| Level 3 |
Hardened build platform, non-falsifiable provenance |
| Level 4 |
Two-party review, hermetic builds |
References
Other files in this skill
assets/template.md (verbatim)
in-toto Supply Chain Security Assessment Template
| Field |
Value |
| Project Name |
|
| Repository |
|
| Container Registry |
|
| in-toto Version |
|
| Assessment Date |
|
| Assessed By |
|
Supply Chain Layout
Pipeline Steps
| Step |
Functionary |
Key Type |
Threshold |
Artifacts |
| checkout |
|
|
|
|
| build |
|
|
|
|
| test |
|
|
|
|
| scan |
|
|
|
|
| push |
|
|
|
|
Key Management
Verification Checklist
SLSA Compliance
| Level |
Requirement |
Status |
| L1 |
Build process documented |
|
| L2 |
Signed provenance from hosted build |
|
| L3 |
Hardened build platform |
|
| L4 |
Two-party review + hermetic build |
|
Sign-Off
| Role |
Name |
Date |
| Security Engineer |
|
|
| Release Manager |
|
|
references/api-reference.md (verbatim)
API Reference: in-toto Supply Chain Security
Libraries Used
| Library |
Purpose |
in_toto |
Python reference implementation for supply chain verification |
securesystemslib |
Cryptographic key management and signing |
subprocess |
Execute in-toto-run and in-toto-verify CLI commands |
json |
Parse link metadata and layout files |
Installation
pip install in-toto 'securesystemslib[crypto]'
CLI Commands
Record a Supply Chain Step
# Record a build step (creates a link metadata file)
in-toto-run --step-name build \
--key functionary-key \
--materials src/ \
--products dist/ \
-- make build
# Record a test step
in-toto-run --step-name test \
--key tester-key \
--materials dist/ \
--products test-results/ \
-- pytest tests/
Verify the Supply Chain
# Verify all steps match the layout
in-toto-verify --layout root.layout \
--layout-keys project-owner-pub.key
Generate Signing Keys
# Generate an Ed25519 keypair
in-toto-keygen --type ed25519 --output functionary-key
Python API
Create a Supply Chain Layout
from in_toto.models.layout import Layout, Step, Inspection
from in_toto.models.metadata import Metadata
from securesystemslib.interface import import_ed25519_privatekey_from_file
# Load the project owner's private key
owner_key = import_ed25519_privatekey_from_file("owner-key")
# Define the supply chain layout
layout = Layout()
layout.expires = "2026-01-01T00:00:00Z"
# Step 1: Source code checkout
step_clone = Step(name="clone")
step_clone.expected_materials = []
step_clone.expected_products = [["CREATE", "src/*"]]
step_clone.pubkeys = [functionary_keyid]
step_clone.expected_command = ["git", "clone", "https://github.com/org/repo.git"]
# Step 2: Build
step_build = Step(name="build")
step_build.expected_materials = [
["MATCH", "src/*", "WITH", "PRODUCTS", "FROM", "clone"]
]
step_build.expected_products = [["CREATE", "dist/*"]]
step_build.pubkeys = [functionary_keyid]
# Step 3: Test
step_test = Step(name="test")
step_test.expected_materials = [
["MATCH", "dist/*", "WITH", "PRODUCTS", "FROM", "build"]
]
step_test.expected_products = [["CREATE", "test-results/*"]]
step_test.pubkeys = [tester_keyid]
layout.steps = [step_clone, step_build, step_test]
# Add an inspection (run at verification time)
inspection = Inspection(name="verify-checksums")
inspection.expected_materials = [
["MATCH", "dist/*", "WITH", "PRODUCTS", "FROM", "build"]
]
inspection.run = ["sha256sum", "dist/*"]
layout.inspect = [inspection]
# Sign and write the layout
metadata = Metadata(signed=layout)
metadata.sign(owner_key)
metadata.dump("root.layout")
Record a Step Programmatically
from in_toto.runlib import in_toto_run
# Record a step with materials and products
link = in_toto_run(
name="build",
material_list=["src/"],
product_list=["dist/"],
signing_key=functionary_key,
record_streams=True,
command=["make", "build"],
)
# Saves build.{keyid-prefix}.link
Verify the Supply Chain
from in_toto.verifylib import in_toto_verify
# Verify all steps and inspections
summary = in_toto_verify(
metadata=layout_metadata,
layout_key_dict={owner_keyid: owner_pubkey},
)
# Raises an exception if verification fails
from in_toto.models.metadata import Metadata
link_metadata = Metadata.load("build.abc123.link")
link = link_metadata.signed
print(f"Step: {link.name}")
print(f"Command: {link.command}")
print(f"Materials: {list(link.materials.keys())}")
print(f"Products: {list(link.products.keys())}")
print(f"Return value: {link.byproducts.get('return-value')}")
Key Concepts
| Concept |
Description |
| Layout |
Defines the expected supply chain steps, who performs them, and material/product rules |
| Step |
A single supply chain operation (clone, build, test, package) |
| Link |
Metadata recorded when a step is actually performed (materials, products, command) |
| Inspection |
Verification commands run at verification time |
| Functionary |
A person or CI system authorized to perform a step |
| Materials |
Input files consumed by a step |
| Products |
Output files produced by a step |
{
"signatures": [{"keyid": "abc123...", "sig": "..."}],
"signed": {
"_type": "link",
"name": "build",
"command": ["make", "build"],
"materials": {
"src/main.py": {"sha256": "a1b2c3..."}
},
"products": {
"dist/app.tar.gz": {"sha256": "d4e5f6..."}
},
"byproducts": {
"return-value": 0,
"stdout": "Build successful",
"stderr": ""
}
}
}
references/standards.md (verbatim)
Standards and References - Supply Chain Security with in-toto
Industry Standards
SLSA (Supply chain Levels for Software Artifacts)
- in-toto provides the attestation framework that SLSA builds upon
- SLSA provenance attestations use in-toto attestation format
- Graduated to v1.0 specification with clear level requirements
NIST SSDF (Secure Software Development Framework) SP 800-218
- PO.1.1: Define and document security requirements for software
- PS.1.1: Verify third-party software components
- PW.4.1: Review and analyze source code for security vulnerabilities
NIST SP 800-204D: Strategies for Securing the Software Supply Chain
- Section 4: Build system integrity verification
- Section 5: Attestation-based supply chain verification
- Recommends cryptographic provenance tracking
Executive Order 14028 (Improving the Nation's Cybersecurity)
- Requires SBOM generation for software sold to federal government
- Mandates supply chain security for critical software
- in-toto attestations satisfy provenance requirements
Compliance Mapping
| Requirement |
Framework |
in-toto Capability |
| Build provenance |
SLSA L2+ |
Signed link metadata per build step |
| Artifact integrity |
NIST 800-204D |
SHA-256 hash chaining between steps |
| Authorized builders |
SLSA L3+ |
Functionary key verification |
| SBOM generation |
EO 14028 |
Inspection step for SBOM validation |
| Code review |
SLSA L4 |
Threshold signing with multiple reviewers |
| Tamper detection |
PCI DSS 6.5 |
End-to-end verification before deployment |
Ecosystem Integration
Sigstore
- Keyless signing via Fulcio certificate authority
- Transparency log via Rekor for attestation persistence
- Cosign for container image signing and verification
Witness / Archivista
- Witness: in-toto implementation focused on cloud-native CI/CD
- Archivista: Attestation storage and retrieval service
- Both used by SolarWinds for supply chain integrity post-breach
OpenVEX
- Vulnerability Exploitability eXchange format
- Complements in-toto attestations with vulnerability status
- Allows marking CVEs as "not affected" for specific builds
references/workflows.md (verbatim)
Workflows - Supply Chain Security with in-toto
Implementation Workflow
Phase 1: Layout Design
- Map your CI/CD pipeline steps (source, build, test, scan, package, push)
- Identify functionaries for each step (CI runner, scanner, reviewer)
- Define artifact flow between steps (what inputs/outputs)
- Generate signing keys for each functionary
- Create and sign the supply chain layout
Phase 2: Pipeline Integration
- Wrap each CI/CD step with
in-toto-run to generate link metadata
- Configure key management (Vault, KMS, or Sigstore keyless)
- Store link metadata alongside build artifacts
- Verify supply chain at end of pipeline before push to registry
- Attach attestations to container images via cosign
Phase 3: Deployment Verification
- Deploy admission webhook for in-toto verification
- Configure policy engine to require valid attestations
- Test with known-good and known-bad attestation chains
- Enable enforcement mode to block unverified images
- Monitor verification failures and alert on anomalies
CI/CD Pipeline Integration
GitHub Actions Example
jobs:
build:
steps:
- uses: actions/checkout@v4
- name: Record checkout step
run: |
in-toto-run --step-name checkout \
--key ${{ secrets.BUILDER_KEY }} \
--products Dockerfile src/* \
-- echo "checkout complete"
- name: Build and record
run: |
in-toto-run --step-name build \
--key ${{ secrets.BUILDER_KEY }} \
--materials Dockerfile src/* \
--products image-digest.txt \
-- docker build -t app:${{ github.sha }} .
- name: Scan and record
run: |
in-toto-run --step-name scan \
--key ${{ secrets.SCANNER_KEY }} \
--materials image-digest.txt \
--products vuln-report.json sbom.json \
-- trivy image app:${{ github.sha }}
- name: Verify chain
run: |
in-toto-verify --layout root.layout \
--layout-key keys/owner.pub
Key Rotation Workflow
- Generate new key pair for the functionary
- Update the supply chain layout with new public key
- Re-sign the layout with the owner key
- Distribute new private key to the functionary (via secrets manager)
- Revoke the old key after transition period
- Verify builds use new key going forward
Incident Response Workflow
Supply Chain Compromise Detected
- Identify which step's attestation is invalid or missing
- Check if functionary key was compromised
- Review link metadata for the affected step
- Compare artifact hashes against known-good builds
- If compromise confirmed: revoke affected keys, rebuild from verified source
- Update layout to add additional verification requirements
Back to mukul975/Anthropic-Cybersecurity-Skills (817 security skills) or Agent skills.