By Sagar Shankaran, Founder of CallSphere
Protect your AI agent systems from supply chain attacks by implementing dependency scanning, tool artifact verification, signed packages, software bill of materials (SBOM), and continuous vulnerability monitoring.
Key takeaways
AI agents depend on a deep stack of libraries: LLM client SDKs, tool integrations, vector database clients, serialization libraries, and framework code. A compromised dependency anywhere in this stack can exfiltrate data, inject malicious behavior, or provide a backdoor into your agent infrastructure.
The attack surface for agent supply chains is larger than typical applications because agents often dynamically load tools and plugins at runtime. A malicious tool registered in your agent's tool catalog can execute arbitrary code with the agent's full permissions.
Automate vulnerability scanning for every dependency in your agent's stack. Integrate scanning into your CI/CD pipeline so vulnerable packages are caught before deployment:
Hear it before you finish reading
Talk to a live CallSphere AI voice agent for logistics in your browser — 60 seconds, no signup.
flowchart LR
INPUT(["User intent"])
PARSE["Parse plus<br/>classify"]
PLAN["Plan and tool<br/>selection"]
AGENT["Agent loop<br/>LLM plus tools"]
GUARD{"Guardrails<br/>and policy"}
EXEC["Execute and<br/>verify result"]
OBS[("Trace and metrics")]
OUT(["Outcome plus<br/>next action"])
INPUT --> PARSE --> PLAN --> AGENT --> GUARD
GUARD -->|Pass| EXEC --> OUT
GUARD -->|Fail| AGENT
AGENT --> OBS
style AGENT fill:#4f46e5,stroke:#4338ca,color:#fff
style GUARD fill:#f59e0b,stroke:#d97706,color:#1f2937
style OBS fill:#ede9fe,stroke:#7c3aed,color:#1e1b4b
style OUT fill:#059669,stroke:#047857,color:#fff
import subprocess
import json
from dataclasses import dataclass
@dataclass
class VulnerabilityReport:
package: str
version: str
severity: str
cve_id: str
description: str
fixed_version: str | None
class DependencyScanner:
"""Scans Python agent dependencies for known vulnerabilities."""
def scan_requirements(self, requirements_path: str) -> list[VulnerabilityReport]:
"""Run pip-audit on a requirements file."""
result = subprocess.run(
[
"pip-audit",
"--requirement", requirements_path,
"--format", "json",
"--strict",
],
capture_output=True,
text=True,
)
if result.returncode == 0:
return [] # No vulnerabilities found
try:
audit_data = json.loads(result.stdout)
except json.JSONDecodeError:
return []
reports = []
for dep in audit_data.get("dependencies", []):
for vuln in dep.get("vulns", []):
reports.append(
VulnerabilityReport(
package=dep["name"],
version=dep["version"],
severity=vuln.get("fix_versions", ["unknown"])[0],
cve_id=vuln.get("id", "N/A"),
description=vuln.get("description", ""),
fixed_version=vuln.get("fix_versions", [None])[0],
)
)
return reports
def check_policy(
self, reports: list[VulnerabilityReport], max_severity: str = "high"
) -> bool:
"""Return True if all vulnerabilities are within acceptable severity."""
severity_order = ["low", "medium", "high", "critical"]
max_idx = severity_order.index(max_severity)
for report in reports:
sev = report.severity.lower()
if sev in severity_order and severity_order.index(sev) > max_idx:
return False
return True
scanner = DependencyScanner()
vulns = scanner.scan_requirements("requirements.txt")
if not scanner.check_policy(vulns):
print("BLOCKING DEPLOYMENT: Critical vulnerabilities found")
for v in vulns:
print(f" {v.package}=={v.version}: {v.cve_id}")
When agents load tools dynamically, verify that tool artifacts are authentic and untampered. Use cryptographic signatures to establish a chain of trust:
import hashlib
import hmac
from pathlib import Path
class ToolVerifier:
"""Verifies the integrity and authenticity of agent tool packages."""
def __init__(self, signing_key: bytes):
self.signing_key = signing_key
def sign_tool(self, tool_path: str) -> str:
"""Generate a signature for a tool artifact."""
file_hash = self._compute_hash(tool_path)
signature = hmac.new(
self.signing_key, file_hash.encode(), hashlib.sha256
).hexdigest()
return signature
def verify_tool(self, tool_path: str, expected_signature: str) -> bool:
"""Verify that a tool artifact matches its signature."""
file_hash = self._compute_hash(tool_path)
computed_signature = hmac.new(
self.signing_key, file_hash.encode(), hashlib.sha256
).hexdigest()
return hmac.compare_digest(computed_signature, expected_signature)
def _compute_hash(self, file_path: str) -> str:
sha256 = hashlib.sha256()
with open(file_path, "rb") as f:
for chunk in iter(lambda: f.read(8192), b""):
sha256.update(chunk)
return sha256.hexdigest()
class SecureToolLoader:
"""Loads tools only after verifying their signatures."""
def __init__(self, verifier: ToolVerifier, manifest_path: str):
self.verifier = verifier
self.manifest = self._load_manifest(manifest_path)
def _load_manifest(self, path: str) -> dict[str, str]:
"""Load the tool signature manifest."""
manifest = {}
with open(path) as f:
for line in f:
parts = line.strip().split(" ", 1)
if len(parts) == 2:
manifest[parts[1]] = parts[0]
return manifest
def load_tool(self, tool_name: str, tool_path: str):
"""Load a tool only if its signature is valid."""
expected_sig = self.manifest.get(tool_name)
if expected_sig is None:
raise SecurityError(f"Tool '{tool_name}' not in manifest")
if not self.verifier.verify_tool(tool_path, expected_sig):
raise SecurityError(
f"Tool '{tool_name}' signature mismatch — possible tampering"
)
# Safe to load
return self._import_tool(tool_path)
def _import_tool(self, path: str):
import importlib.util
spec = importlib.util.spec_from_file_location("tool", path)
if spec and spec.loader:
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
raise ImportError(f"Cannot load tool from {path}")
class SecurityError(Exception):
pass
Generate and maintain an SBOM for your agent system. An SBOM is a complete inventory of every component, enabling rapid vulnerability response when a new CVE is announced:
import json
from datetime import datetime
class SBOMGenerator:
"""Generates CycloneDX-format SBOM for agent dependencies."""
def generate(self, project_name: str, requirements_path: str) -> dict:
"""Parse requirements and produce a CycloneDX SBOM."""
components = self._parse_requirements(requirements_path)
sbom = {
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"version": 1,
"metadata": {
"timestamp": datetime.utcnow().isoformat(),
"component": {
"type": "application",
"name": project_name,
},
},
"components": components,
}
return sbom
def _parse_requirements(self, path: str) -> list[dict]:
components = []
with open(path) as f:
for line in f:
line = line.strip()
if not line or line.startswith("#"):
continue
parts = line.split("==")
name = parts[0].strip()
version = parts[1].strip() if len(parts) > 1 else "unknown"
components.append({
"type": "library",
"name": name,
"version": version,
"purl": f"pkg:pypi/{name}@{version}",
})
return components
def save(self, sbom: dict, output_path: str) -> None:
with open(output_path, "w") as f:
json.dump(sbom, f, indent=2)
# Generate SBOM during CI/CD
generator = SBOMGenerator()
sbom = generator.generate("research-agent", "requirements.txt")
generator.save(sbom, "sbom.json")
Scan on every CI/CD build and at least daily for deployed systems. New CVEs are published continuously, and a package that was safe yesterday may have a critical vulnerability today. Use tools like Dependabot, Snyk, or pip-audit with scheduled runs. For agents that dynamically load tools, scan the tool registry every time a new tool is registered.
Still reading? Stop comparing — try CallSphere live.
See the logistics AI agent handle a real call — complete, industry-specific, and live in your browser. No signup.
Package checksums (like pip's hash checking) verify that you downloaded the exact file the package index served. Signing goes further — it verifies that the artifact was produced by a trusted party. If an attacker compromises the package index and replaces a package with a malicious version, checksums will match the malicious file. Signatures from the original author will not.
Vendoring (copying dependencies into your repository) protects against supply chain attacks where a package is removed or replaced on the package index. It trades disk space for availability and integrity. For critical agent systems, vendoring combined with signature verification provides the strongest supply chain guarantees.
#SupplyChainSecurity #SBOM #DependencyScanning #AgentDependencies #SoftwareSecurity #AgenticAI #LearnAI #AIEngineering

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
AIBOM is the SBOM equivalent for AI systems. The competing 2026 standards (CycloneDX-AI, SPDX-AI), what they capture, and which is winning.
CISA's 2025 SBOM guidance brings AI and SaaS into scope. Here is the SBOM architecture for a HIPAA-aligned AI voice platform — first-party services, model artifacts, and sub-processor declarations.
Generate a CycloneDX SBOM + ML-BOM for an AI voice agent, attest SLSA provenance with cosign, verify with policy in Kubernetes via Kyverno. Real CI YAML and policy.
Zero trust architecture for AI secures the ML pipeline from data ingestion to model serving with supply chain security, model signing, and container attestation strategies.
How generative AI produces verified dbt models for data migration — from scratch and incrementally — with SME validation and strict data governance.
See how Circini's automated incident management pipeline turns alert emails into triaged Jira tickets using Snowflake Cortex AI, GPT-4.1, Airflow & MS Teams.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco