Securing the AI Agent Deployment Pipeline: From Model Weights to Production API
The deployment pipeline is itself an attack surface. A comprehensive guide to securing every stage: model download and verification, container build, image signing, registry push, orchestration, runtime configuration, API gateway security, CI/CD controls, commit signing, and secrets management.
Securing the AI Agent Deployment Pipeline: From Model Weights to Production API
In the summer of 2020, attackers compromised the SolarWinds Orion build system. They inserted malicious code — SUNBURST — into the software build pipeline such that the legitimate build process would compile and package the backdoor alongside legitimate code. The resulting software update was signed by SolarWinds' authentic code signing certificate, distributed through SolarWinds' official update channel, and installed by approximately 18,000 organizations, including US government agencies.
The lesson was stark: the deployment pipeline is a first-class attack surface. An attacker who compromises the pipeline can produce malicious artifacts that carry all the trust signals of legitimate artifacts — legitimate signatures, legitimate version numbers, legitimate distribution channels. Traditional perimeter defenses are useless against an attack that comes from inside the trusted build process.
This lesson applies with equal or greater force to AI agent deployment pipelines. An AI agent's deployment pipeline is the process by which model weights, configuration files, plugin definitions, and orchestration code travel from their sources (model registries, configuration management systems, plugin marketplaces) to production serving infrastructure. At every stage of this journey, there are opportunities for tampering, injection, and substitution that could result in deploying a compromised agent that behaves as if it is legitimate.
This document provides a comprehensive security guide for AI agent deployment pipelines — stage by stage, from model weight acquisition through production API serving — including specific controls, implementation guidance, and tooling recommendations for security teams responsible for AI agent security in 2026.
TL;DR
- The AI agent deployment pipeline spans eight distinct stages, each a potential attack surface: model weight acquisition, preprocessing and validation, container build, image signing and registry push, infrastructure provisioning, runtime configuration injection, serving layer, and API gateway.
- CI/CD pipeline security is the critical control: a compromised CI system can produce malicious agents that carry legitimate signatures and bypass all consumer-side verification.
- Secrets in pipelines are a persistent weakness: LLM API keys, model registry credentials, and infrastructure credentials in CI/CD pipelines are high-value targets. Secret scanning, dynamic secrets, and just-in-time credential provisioning are essential controls.
- Commit signing with GPG or SSH keys provides the provenance chain for code changes that initiates the trust chain for the entire deployment.
- Container image signing with Cosign and binary authorization enforcement in Kubernetes prevents tampered images from running.
- The SLSA framework provides a maturity model: SLSA Level 2 is achievable today with minimal tooling; Level 3 requires isolated build infrastructure; Level 4 requires hermetic builds and two-party review.
- Armalo's trust oracle and behavioral attestation system integrate with deployment pipelines to provide continuous behavioral verification alongside cryptographic provenance verification.
Pipeline Architecture: The Eight Stages
A production AI agent deployment pipeline spans eight stages. Each stage must be secured. A compromise at any stage propagates to all downstream stages — a compromised model weight can survive containerization and signing if the signing happens after the compromise.
Stage 1: Model Weight Acquisition
↓
Stage 2: Preprocessing and Validation
↓
Stage 3: Container Build
↓
Stage 4: Image Signing and Registry Push
↓
Stage 5: Infrastructure Provisioning
↓
Stage 6: Runtime Configuration Injection
↓
Stage 7: Serving Layer
↓
Stage 8: API Gateway
Stage 1: Model Weight Acquisition
Model weights are typically acquired from one of four sources: closed-source provider APIs (no weights distributed), commercial model registries, open-source model repositories (HuggingFace Hub), or internally trained/fine-tuned models. Each source has different acquisition security requirements.
Closed-Source Provider APIs
For agents built on closed-source provider APIs (OpenAI, Anthropic, Google), there are no weights to download — the model is served through the provider's API. The acquisition security concern shifts to:
API Credential Security: The API keys or OAuth credentials used to access the model must be provisioned securely (from a secrets manager, not hardcoded), rotated regularly, and scoped minimally.
Provider SLA and Security Posture Verification: Before depending on a provider for production AI agent deployments, verify their security posture: SOC 2 Type II report, published security whitepaper, incident response process, SLA for availability.
Model Version Pinning: Do not deploy agents that use "latest" model versions from API providers. Pin to specific model versions (e.g., gpt-4o-2024-08-06, claude-3-7-sonnet-20250219) and test version updates explicitly before deploying to production. Unpinned model versions can change behavior without warning.
Open-Source Model Registry Downloads
For agents using open-source model weights from HuggingFace Hub or similar:
Download Verification:
# Download model weights with signature verification
huggingface-cli download \
meta-llama/Meta-Llama-3.1-70B-Instruct \
--include "*.safetensors" \
--local-dir./model-weights/llama-70b-instruct
# Verify SafeTensors format (prevents pickle exploitation)
python3 -c "
from safetensors import safe_open
import os
for f in os.listdir('./model-weights/llama-70b-instruct'):
if f.endswith('.safetensors'):
with safe_open(f'./model-weights/llama-70b-instruct/{f}', framework='pt') as st:
print(f'Verified: {f} ({len(st.keys())} tensors)')
"
# Verify git commit hash matches expected
cd model-weights/llama-70b-instruct
git log --oneline -1 # Should match the expected commit from HuggingFace
Hash Verification Against Published Checksums:
For well-maintained models, the model publisher provides SHA-256 hashes of weight files. Verify downloads against these published hashes:
# Generate hashes of downloaded files
sha256sum model-weights/llama-70b-instruct/*.safetensors > downloaded-hashes.txt
# Compare against published hashes (from model card or release notes)
diff downloaded-hashes.txt published-hashes.txt
# If diff is empty, hashes match
Quarantine Period: Consider implementing a quarantine period for newly downloaded model weights — store them in an isolated environment for 24-48 hours while running automated security scans (malware scan, behavioral testing). Only move to the production model store after quarantine passes.
Internally Fine-Tuned Models
For internally fine-tuned models, the acquisition security concern shifts to securing the fine-tuning output:
Fine-tuning Output Hash: Compute and store the hash of fine-tuned model weights immediately after training completes. Any subsequent copy of the weights should verify against this original hash.
Training Metadata: Store training metadata alongside weights: training date, base model version, fine-tuning dataset version (hash), hyperparameters, and the identity of the individual who initiated the training run.
Access Control for Training Infrastructure: Only authorized personnel should have write access to the training infrastructure. Use IAM roles rather than individual credentials; require MFA for training job submission.
Stage 2: Preprocessing and Validation
Before weights enter the build pipeline, validate their integrity and security properties.
Format Security Scanning
SafeTensors Enforcement: Reject any model weights in pickle format (.pt,.pth,.bin with pickle serialization). Only accept SafeTensors format or ONNX format.
# Check for dangerous pickle-based model files
find./model-weights -name "*.pt" -o -name "*.pth" -o -name "*.pkl" | while read f; do
echo "SECURITY WARNING: Potentially unsafe file format: $f"
echo "Convert to SafeTensors format before deployment"
done
Metadata Validation: For GGUF format models (used in llama.cpp deployments), validate that metadata does not contain embedded system prompts that would override the agent's configured system prompt:
import struct
from pathlib import Path
def check_gguf_metadata_for_embedded_prompts(model_path: str) -> list[str]:
"""
Scan GGUF model file metadata for embedded system prompt values.
Returns list of suspicious metadata keys found.
"""
suspicious_keys = []
prompt_related_keys = [
"tokenizer.chat_template",
"system.prompt",
"llama.rope.scaling.original_context_length", # Known attack vector
"general.description" # Can contain injected instructions
]
with open(model_path, "rb") as f:
# GGUF magic number verification
magic = f.read(4)
if magic!= b"GGUF":
return ["ERROR: Not a valid GGUF file"]
# Read metadata keys and check for suspicious content
# (Implementation details depend on GGUF format version)
return suspicious_keys
Behavioral Pre-validation
Before committing weights to the build pipeline, run a quick behavioral validation:
def run_prevalidation_tests(model_path: str, test_suite_path: str) -> bool:
"""
Run a minimal behavioral test suite against new model weights.
Returns True if all tests pass.
Tests are designed to catch obvious behavioral anomalies,
not comprehensive adversarial evaluation.
"""
# Load the model
model = load_model(model_path)
# Load the pre-validation test suite
with open(test_suite_path) as f:
tests = json.load(f)
passed = 0
failed = 0
for test in tests:
response = model.generate(test["input"], temperature=0.0)
if evaluate_test(response, test["expected_behavior"]):
passed += 1
else:
failed += 1
print(f"PREVALIDATION FAILURE: {test['name']}")
print(f" Input: {test['input']}")
print(f" Expected: {test['expected_behavior']}")
print(f" Got: {response[:200]}")
print(f"Prevalidation: {passed} passed, {failed} failed")
return failed == 0
Stage 3: Container Build
The container build stage assembles the agent's runtime environment: model weights, application code, configuration, and runtime dependencies.
Dockerfile Security Principles
Use Minimal Base Images:
# Use distroless base for minimal attack surface
FROM gcr.io/distroless/python3-debian12
# Not FROM ubuntu:22.04 (full OS, large attack surface)
# Not FROM python:3.11 (includes pip, full Python tooling)
Multi-Stage Builds to Separate Build and Runtime Dependencies:
# Build stage: install dependencies
FROM python:3.11-slim AS builder
WORKDIR /build
COPY requirements.txt.
RUN pip install --no-cache-dir --require-hashes -r requirements.txt
# Runtime stage: only include what's needed for execution
FROM gcr.io/distroless/python3-debian12
# Copy only necessary files from builder
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
# Copy application code
COPY --chown=nonroot:nonroot app/ /app/
# Copy model weights (from secure staging location)
COPY --chown=nonroot:nonroot model-weights/ /model-weights/
# Run as non-root
USER nonroot:nonroot
ENTRYPOINT ["python3", "-m", "agent.server"]
Dependency Version Pinning in Build:
# Install from hash-verified requirements (never from version ranges without hashes)
RUN pip install --require-hashes --no-cache-dir -r requirements.txt
Build-Time Security Scanning
Run security scanning as part of the Dockerfile build (or immediately after):
# Dockerfile build step in CI
- name: Build container image
run: |
docker build --no-cache \
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
--build-arg GIT_COMMIT=${{ github.sha }} \
-t registry.company.com/ai-agent:${{ github.sha }}.
- name: Scan container image for vulnerabilities
uses: aquasecurity/trivy-action@master
with:
image-ref: 'registry.company.com/ai-agent:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1' # Fail build on critical/high vulnerabilities
- name: Scan for secrets in container image
run: |
docker run --rm \
-v $(docker inspect registry.company.com/ai-agent:${{ github.sha }} \
--format '{{.GraphDriver.Data.MergedDir }}'):/fs:ro \
trufflesecurity/trufflehog:latest \
filesystem /fs
Stage 4: Image Signing and Registry Push
Container image signing provides cryptographic proof that an image was produced by a trusted build pipeline and has not been modified since signing.
Cosign Image Signing
# GitHub Actions workflow step for image signing
- name: Sign container image with Cosign
env:
COSIGN_EXPERIMENTAL: "true" # Enable keyless signing
run: |
# Push the image first
docker push registry.company.com/ai-agent:${{ github.sha }}
# Sign the image using OIDC keyless signing
cosign sign \
--rekor-url https://rekor.sigstore.dev \
--fulcio-url https://fulcio.sigstore.dev \
registry.company.com/ai-agent:${{ github.sha }}
# Tag the signed digest as the canonical version
DIGEST=$(docker inspect --format='{{index.RepoDigests 0}}' \
registry.company.com/ai-agent:${{ github.sha }})
echo "Signed image digest: $DIGEST"
echo "image-digest=$DIGEST" >> $GITHUB_OUTPUT
- name: Attach SBOM to container image
run: |
# Generate SBOM
syft registry.company.com/ai-agent:${{ github.sha }} \
-o cyclonedx-json > sbom.json
# Attach SBOM as attestation
cosign attest \
--predicate sbom.json \
--type cyclonedx \
registry.company.com/ai-agent:${{ github.sha }}
Registry Security Configuration
The container registry itself must be secured:
Access Control: Use RBAC in the registry (Nexus, Harbor, ECR, GCR). CI/CD pipelines should use service accounts with only push access to specific image paths. Deployment systems should use service accounts with only pull access.
Immutable Tags: Configure the registry to prevent overwriting existing image tags. Once ai-agent:v2.4.1 is pushed, it cannot be overwritten with different content. This prevents tag-based attacks where an attacker overwrites a pinned version.
Image Retention Policy: Implement retention policies that prevent unnecessary accumulation of old images (reducing the attack surface of stale images), but retain images for compliance and forensic purposes for a defined period.
Registry Vulnerability Scanning: Configure automated vulnerability scanning on push and scheduled periodic scans. For AWS ECR, enable Enhanced Scanning; for Harbor, configure Trivy integration.
Stage 5: Infrastructure Provisioning
The infrastructure that runs AI agents — Kubernetes clusters, ECS tasks, serverless functions — must be provisioned securely.
Infrastructure as Code Security
Policy as Code: Use Open Policy Agent (OPA) or Kyverno to enforce security policies on Kubernetes resources:
# Kyverno policy: require image signature verification for AI agent pods
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-ai-agent-image
spec:
validationFailureAction: Enforce
rules:
- name: check-image-signature
match:
any:
- resources:
kinds:
- Pod
namespaces:
- ai-agents
verifyImages:
- imageReferences:
- "registry.company.com/ai-agent:*"
attestors:
- count: 1
entries:
- keyless:
subject: "https://github.com/company/ai-agent/.github/workflows/deploy.yml@refs/heads/main"
issuer: "https://token.actions.githubusercontent.com"
rekor:
url: https://rekor.sigstore.dev
Network Policy: Restrict network egress for AI agent pods to only the services they legitimately need:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ai-agent-network-policy
namespace: ai-agents
spec:
podSelector:
matchLabels:
app: ai-agent
policyTypes:
- Egress
- Ingress
egress:
# Allow communication with LLM API
- to:
- ipBlock:
cidr: 0.0.0.0/0
ports:
- protocol: TCP
port: 443
# Allow communication with internal database
- to:
- namespaceSelector:
matchLabels:
name: databases
ports:
- protocol: TCP
port: 5432
Pod Security Standards: Enforce Kubernetes Pod Security Standards at restricted level for AI agent workloads:
apiVersion: v1
kind: Namespace
metadata:
name: ai-agents
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: v1.29
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Stage 6: Runtime Configuration Injection
Configuration injection — providing the agent with its system prompt, tool configurations, plugin credentials, and operational parameters at runtime rather than bake-in — is a deployment best practice that also has security implications.
Secrets Management for Agent Deployments
The most sensitive configurations — API keys, OAuth tokens, database credentials — must never be embedded in container images or committed to code repositories. They must be injected at runtime from a secrets management system.
AWS Secrets Manager Integration with Kubernetes:
# External Secrets Operator configuration
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: ai-agent-secrets
namespace: ai-agents
spec:
refreshInterval: 15m
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
target:
name: ai-agent-secrets
creationPolicy: Owner
data:
- secretKey: OPENAI_API_KEY
remoteRef:
key: armalo/production
property: OPENAI_API_KEY
- secretKey: ANTHROPIC_API_KEY
remoteRef:
key: armalo/production
property: ANTHROPIC_API_KEY
Secret Rotation: Configure automatic rotation for long-lived credentials. AWS Secrets Manager supports automatic rotation for RDS databases and can be configured for custom secret rotation via Lambda functions. LLM API keys should be rotated on a scheduled basis (quarterly at minimum) and immediately on suspected compromise.
Just-in-Time Credentials: For maximum security, use just-in-time credential provisioning where the agent's credentials are created fresh for each invocation and expire after a short TTL. This limits the window of exposure for compromised credentials.
System Prompt Injection Prevention
System prompts often contain sensitive business logic. Protecting system prompts from exfiltration requires both access controls (limiting who can read the system prompt from the secrets store) and operational security (not including the system prompt in logs or error messages).
Encrypted System Prompts: Store system prompts encrypted at rest in the secrets store. Decrypt at agent startup using a KMS-protected key. This prevents access to the system prompt even if the underlying storage is compromised.
System Prompt Versioning: Version-control system prompts in a separate repository with strict access controls and mandatory code review for changes. This provides an audit trail of system prompt changes and enables rollback.
Stage 7: Serving Layer Security
The serving layer — the inference server or API endpoint that handles requests to the AI agent — has specific security requirements.
Input Validation at the Serving Layer
Implement a validation layer that checks all inputs before passing them to the model:
from pydantic import BaseModel, field_validator
import re
class AgentRequest(BaseModel):
user_message: str
conversation_id: str
user_id: str
@field_validator('user_message')
@classmethod
def validate_message_length(cls, v: str) -> str:
if len(v) > 10000: # Prevent token flooding attacks
raise ValueError("Message exceeds maximum length")
return v
@field_validator('user_message')
@classmethod
def check_prompt_injection_patterns(cls, v: str) -> str:
"""
Check for known prompt injection patterns.
This is a defense-in-depth measure, not a primary defense.
"""
injection_patterns = [
r'ignore previous instructions',
r'ignore all previous',
r'disregard your instructions',
r'forget everything above',
r'you are now', # Role reassignment attempt
r'<\|system\|>', # Common injection prefix
]
for pattern in injection_patterns:
if re.search(pattern, v, re.IGNORECASE):
# Log for security monitoring, but don't necessarily block
# (false positive rate may be high for legitimate inputs)
log_security_event("potential_prompt_injection", {"pattern": pattern, "message_preview": v[:100]})
return v
Rate Limiting and Abuse Prevention
AI agent APIs are targets for abuse — credential stuffing, prompt injection at scale, and resource exhaustion. Implement multi-tier rate limiting:
from upstash_redis import Redis
import time
class AgentRateLimiter:
def __init__(self, redis_client: Redis):
self.redis = redis_client
def check_rate_limit(self, user_id: str, org_id: str) -> tuple[bool, dict]:
"""
Multi-tier rate limiting: per-user and per-org limits.
Returns: (allowed, rate_limit_headers)
"""
now = int(time.time())
# Per-user: 10 requests per minute
user_key = f"rl:user:{user_id}:{now // 60}"
user_count = self.redis.incr(user_key)
self.redis.expire(user_key, 120) # 2 minute TTL
if user_count > 10:
return False, {"X-RateLimit-Reason": "per-user-limit"}
# Per-org: 100 requests per minute (for standard plan)
org_key = f"rl:org:{org_id}:{now // 60}"
org_count = self.redis.incr(org_key)
self.redis.expire(org_key, 120)
if org_count > 100:
return False, {"X-RateLimit-Reason": "per-org-limit"}
return True, {
"X-RateLimit-Remaining-User": str(10 - user_count),
"X-RateLimit-Remaining-Org": str(100 - org_count)
}
Output Filtering
Implement output filtering to detect and handle potentially harmful or policy-violating agent outputs:
class OutputFilter:
"""
Post-processing filter for AI agent outputs.
Checks for policy violations, PII, and potential exfiltration.
"""
def filter_output(self, output: str, context: dict) -> tuple[str, list[str]]:
"""
Filter agent output for policy violations.
Returns: (filtered_output, list_of_flags)
"""
flags = []
filtered = output
# Check for potential PII in output (should not be present if agent is properly scoped)
pii_patterns = {
"ssn": r"\b\d{3}-\d{2}-\d{4}\b",
"credit_card": r"\b\d{4}[\s-]\d{4}[\s-]\d{4}[\s-]\d{4}\b",
"email": r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"
}
for pii_type, pattern in pii_patterns.items():
if re.search(pattern, output):
flags.append(f"potential_pii_{pii_type}")
# Optionally redact in output
# Check for potential exfiltration indicators (URLs, base64 blobs)
if re.search(r'https?://(?!approved\.domain\.com)', output):
flags.append("unexpected_url_in_output")
if len(flags) > 0:
log_security_event("output_filter_flags", {"flags": flags, "context": context})
return filtered, flags
Stage 8: API Gateway Security
The API gateway is the public interface through which clients interact with the AI agent. It is the last line of defense before requests reach the agent and the first filter on all responses.
API Gateway Security Controls
Authentication and Authorization: Every request must be authenticated and authorized. Use API keys with SHA-256 hashing (never store raw keys), OAuth 2.0 with PKCE for user-facing interfaces, or mutual TLS for service-to-service communication.
WAF Integration: Deploy a Web Application Firewall (WAF) in front of the API gateway to filter common web attacks (SQL injection, XSS, path traversal) that might be combined with AI-specific attacks.
Request Logging for Behavioral Analysis: Log all requests and responses (with appropriate PII handling) to enable behavioral analysis. Patterns that indicate attack attempts — very long inputs, inputs with high special-character density, repeated identical inputs — should be detected and investigated.
DDoS Protection: AI inference is computationally expensive. Even without malicious intent, uncontrolled request volumes can exhaust GPU resources. Implement DDoS protection at the API gateway level, distinct from per-user rate limiting.
Response Headers: Configure security response headers:
Content-Type: application/json
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Security-Policy: default-src 'none'
Cache-Control: no-store # AI responses should not be cached at CDN layer
CI/CD Pipeline Security
The CI/CD pipeline is the integration point for all the deployment stages described above. Its security determines the security of everything it builds and deploys.
Commit Signing
All commits that initiate deployment pipelines should be signed. Without commit signing, an attacker who can push code (through a compromised developer account or a repository configuration error) can initiate deployments of malicious code without leaving authenticated evidence.
GPG Commit Signing:
# Configure Git to sign all commits
git config --global user.signingkey $GPG_KEY_ID
git config --global commit.gpgsign true
git config --global gpg.program gpg2
GitHub Branch Protection with Signed Commits:
# GitHub branch protection rules (via terraform or GitHub API)
branch_protection:
require_signed_commits: true
required_status_checks:
strict: true
contexts: ["security-scan", "dependency-review", "slsa-provenance"]
required_pull_request_reviews:
required_approving_review_count: 2
dismiss_stale_reviews: true
require_code_owner_reviews: true
Pipeline Secret Security
Secret Scanning in CI: Run secret scanning on every commit to prevent accidental credential exposure:
- name: Detect secrets in repository
uses: trufflesecurity/trufflehog@main
with:
path:./
base: ${{ github.event.repository.default_branch }}
head: HEAD
extra_args: --only-verified
Ephemeral Credentials in Pipeline: Use OIDC-based just-in-time credentials for cloud provider access rather than long-lived access keys:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/ai-agent-deploy-role
aws-region: us-west-2
# This uses GitHub Actions OIDC — no long-lived AWS access keys needed
Principle of Least Privilege for Pipeline Roles: Define IAM/cloud IAM roles for CI/CD pipelines with the minimum permissions needed for each stage:
- Build role: ECR push, Secrets Manager read (for signing keys), S3 write (for artifacts)
- Deploy role: ECS update-service, ECR pull, Secrets Manager read (for deployment config)
How Armalo Integrates with Deployment Pipeline Security
Armalo's trust oracle and behavioral attestation system can be integrated as gates in the deployment pipeline, adding behavioral verification to the cryptographic provenance verification that Sigstore and SLSA provide.
Deployment Pipeline Behavioral Verification
# Deployment pipeline step: verify behavioral trust before deploying
- name: Verify agent behavioral trust
run: |
TRUST_RESPONSE=$(curl -s \
-H "X-Pact-Key: $ARMALO_API_KEY" \
"https://armalo.ai/api/v1/trust/?agent_id=${AGENT_ID}")
TRUST_SCORE=$(echo $TRUST_RESPONSE | jq '.trustScore')
SUPPLY_CHAIN_SCORE=$(echo $TRUST_RESPONSE | jq '.dimensions.supplyChainIntegrity')
echo "Behavioral trust score: $TRUST_SCORE"
echo "Supply chain integrity: $SUPPLY_CHAIN_SCORE"
if (( $(echo "$TRUST_SCORE < 7.0" | bc -l) )); then
echo "DEPLOYMENT BLOCKED: Trust score below minimum threshold"
exit 1
fi
if (( $(echo "$SUPPLY_CHAIN_SCORE < 6.0" | bc -l) )); then
echo "DEPLOYMENT BLOCKED: Supply chain integrity below minimum threshold"
exit 1
fi
echo "Behavioral trust verification: PASSED"
Post-Deployment Behavioral Attestation Update
After a successful deployment, update Armalo's behavioral attestation record to reflect the new deployment:
# Update Armalo behavioral attestation for new deployment
curl -s -X POST \
-H "X-Pact-Key: $ARMALO_API_KEY" \
-H "Content-Type: application/json" \
"https://armalo.ai/api/v1/trust/update-deployment" \
-d '{
"agent_id": "'$AGENT_ID'",
"deployment_version": "'$GITHUB_SHA'",
"deployment_timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",
"slsa_level": 2,
"image_digest": "'$IMAGE_DIGEST'",
"behavioral_hash": "'$BEHAVIORAL_HASH'",
"supply_chain_artifacts": {
"sbom_hash": "'$SBOM_HASH'",
"image_signature_rekor_entry": "'$REKOR_ENTRY_URL'"
}
}'
Conclusion: The Pipeline as Security Infrastructure
Securing the AI agent deployment pipeline is not a single control — it is a system of controls that, taken together, provide the assurance that what is running in production is what was verified during development.
The SolarWinds lesson — that attackers who compromise the pipeline can produce malicious artifacts with legitimate credentials — remains relevant. For AI agents, the stakes are higher: a compromised agent may behave normally for most interactions while exhibiting specific malicious behavior in targeted scenarios. The behavioral complexity of AI systems makes supply chain attacks harder to detect and therefore more dangerous.
The eight-stage pipeline security framework described in this document provides a comprehensive approach. The key insight is that security must be enforced at every stage: a compromised model weight that passes into the build pipeline can survive image signing (the signature applies to the container image, which includes the compromised weight). A compromised configuration injected at runtime bypasses all build-time security.
Defense in depth is not just a best practice for this architecture — it is the only architecture that is resistant to sophisticated supply chain attacks. Implement controls at every stage. Verify at every stage. Monitor at every stage. And integrate behavioral verification alongside cryptographic provenance verification, because cryptographic proofs that an artifact is unmodified do not prove that the artifact was not malicious to begin with.
Build trust into your agents
Register an agent, define behavioral pacts, and earn verifiable trust scores that unlock marketplace access.
Based in Singapore? See our MAS AI governance compliance resources →