Supply chain integrity
Attestd monitors selected PyPI packages for malicious publishes and security-related yanks, alongside CVE-based risk. The supply_chain object in a /v1/check response is independent from risk_state (which reflects NVD-derived vulnerability data only).
Supply chain compromise is deterministic: a package version either has a known malicious publish or it does not. Signals come from three sources: the Attestd registry (human-verified), OSV malicious-package advisories, and PyPI yanks with security annotations. This means you can block deployment before running code from a compromised dependency.
Quick start
Check a PyPI package for supply chain compromise:
# Check a PyPI package for supply chain compromise
curl "https://api.attestd.io/v1/check?product=langchain&version=0.1.0" \
-H "Authorization: Bearer YOUR_API_KEY"A safe package returns compromised: false with an empty sources array.
Example responses
Safe version
{
"product": "langchain",
"version": "0.3.0",
"supported": true,
"risk_state": "none",
"supply_chain": {
"compromised": false,
"sources": [],
"malware_type": null,
"advisory_url": null,
"compromised_at": null,
"removed_at": null
},
"last_updated": "2026-02-23T18:21:30Z"
}Compromised version
When a malicious publish is detected:
{
"product": "langchain",
"version": "0.1.0",
"supported": true,
"risk_state": "none",
"supply_chain": {
"compromised": true,
"sources": ["registry", "osv"],
"malware_type": "typosquatting",
"description": "Version published by malicious actor impersonating official maintainer",
"advisory_url": "https://osv.dev/MAL-2026-1234",
"compromised_at": "2026-02-20T14:32:10Z",
"removed_at": "2026-02-21T09:15:00Z"
},
"last_updated": "2026-02-23T18:21:30Z"
}Using the Python SDK
Check supply chain status in your application or deployment pipeline:
import attestd
client = attestd.Client(api_key="YOUR_API_KEY")
# Check a PyPI package
result = client.check("langchain", "0.3.0")
# Check supply chain signal
if result.supply_chain and result.supply_chain.compromised:
print(f"[ALERT] Malicious version detected: {result.product} {result.version}")
print(f"Detected by: {', '.join(result.supply_chain.sources)}")
print(f"Description: {result.supply_chain.description}")
raise SystemExit("Do not deploy - compromised dependency")
if result.supply_chain is None:
print(f"Note: {result.product} is not in supply chain monitoring")
# Still check CVE risk
if result.risk_state in ("critical", "high"):
raise SystemExit(f"CVE risk detected: {result.risk_state}")
print(f"Safe to proceed: {result.product} {result.version}")Scanning a requirements file
Scan all dependencies in requirements.txt for supply chain compromise before deploying:
# requirements-check.py
import attestd
import re
import sys
def parse_requirements(filename):
"""Parse requirements.txt and return list of (package, version) tuples"""
packages = []
with open(filename) as f:
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue
# Handle == and >= operators
if '==' in line:
pkg, ver = line.split('==')
packages.append((pkg.strip(), ver.strip()))
elif '>=' in line:
pkg, ver = line.split('>=')
packages.append((pkg.strip(), ver.strip()))
return packages
def check_dependencies(filename, api_key):
"""Check all dependencies for supply chain compromise"""
client = attestd.Client(api_key=api_key)
packages = parse_requirements(filename)
compromised = []
for package, version in packages:
try:
result = client.check(package, version)
# Check supply chain compromise
if result.supply_chain and result.supply_chain.compromised:
compromised.append({
'package': package,
'version': version,
'reason': result.supply_chain.description,
'sources': result.supply_chain.sources
})
# Also check CVE risk
if result.risk_state in ("critical", "high"):
compromised.append({
'package': package,
'version': version,
'reason': f"CVE risk: {result.risk_state}",
'cves': result.cve_ids
})
except attestd.AttestdUnsupportedProductError:
# Not in attestd coverage - not necessarily bad, but alert
print(f"[WARNING] {package} not in attestd coverage")
if compromised:
print("[ERROR] Compromised or risky packages found:")
for item in compromised:
print(f" {item['package']}@{item['version']}: {item['reason']}")
sys.exit(1)
else:
print(f"[OK] All {len(packages)} dependencies passed supply chain check")Run this as part of your CI/CD pipeline with:
python requirements-check.py requirements.txtMonitored packages
26 PyPI packages across AI/ML frameworks, data science, vector databases, web frameworks, and cloud SDKs. Use these exact PyPI slugs as the product query parameter. Click any package name to jump to examples below.
LLM / AI frameworks (11)
- litellm (LiteLLM)
- langchain (LangChain)
- langchain-core (LangChain Core)
- langgraph (LangGraph)
- langgraph-checkpoint (LangGraph Checkpoint)
- autogen-agentchat (AutoGen AgentChat)
- autogen-core (AutoGen Core)
- crewai (CrewAI)
- transformers (HuggingFace Transformers)
- openai (OpenAI SDK)
- anthropic (Anthropic SDK)
Data science (5)
- numpy (NumPy)
- pandas (pandas)
- scikit-learn (scikit-learn)
- polars (Polars)
- dask (Dask)
Vector databases (3)
- pinecone (Pinecone)
- qdrant-client (Qdrant Client)
- chromadb (ChromaDB)
Web frameworks (3)
- fastapi (FastAPI)
- django (Django)
- flask (Flask)
Cloud SDKs (3)
- boto3 (boto3 (AWS))
- google-cloud-storage (Google Cloud Storage)
- azure-core (Azure Core SDK)
HTTP utilities (1)
- requests (Requests)
Package-specific examples
Common supply chain checks for packages used in AI and data stacks:
LangChain (AI orchestration)
curl "https://api.attestd.io/v1/check?product=langchain&version=0.3.0" \
-H "Authorization: Bearer YOUR_API_KEY"Requests (HTTP dependency)
curl "https://api.attestd.io/v1/check?product=requests&version=2.31.0" \
-H "Authorization: Bearer YOUR_API_KEY"NumPy (data science)
curl "https://api.attestd.io/v1/check?product=numpy&version=1.24.0" \
-H "Authorization: Bearer YOUR_API_KEY"FastAPI (web framework)
curl "https://api.attestd.io/v1/check?product=fastapi&version=0.115.0" \
-H "Authorization: Bearer YOUR_API_KEY"Sources
- registry (Manually curated YAML in Attestd's repo; fastest human-verified signal (confidence 1.0 when confirming a compromise).
- osv (OSV.dev malicious-packages advisories with IDs prefixed
MAL-(confidence 0.95). - pypi_yank (Versions yanked on PyPI with a security-related
yanked_reasonheuristic (confidence 0.80).
The sources array lists which sources flagged the version (e.g. ["osv", "registry"] when both agree).
Understanding the response
supply_chain: null
Product is not in supply chain monitoring. For example, infrastructure packages (nginx, postgres) or unsupported PyPI packages. This is not a safety signal. Check risk_state for CVE status.
compromised: false, sources: []
Package is monitored and no malicious publish was found at the last ingestion. Safe to use. The last_updated field shows when monitoring last ran; check this if you need the absolute latest data.
compromised: true
A malicious publish has been confirmed. Block deployment immediately. Do not auto-upgrade. Treat as an active incident. The compromised_at and removed_at timestamps indicate when the malicious version appeared and when it was pulled from PyPI.
sources
Which detection mechanisms flagged the compromise. Multiple sources (e.g., ["registry", "osv"]) mean independent confirmations. A single source like ["pypi_yank"] means the version was yanked with a security annotation.
risk_state vs supply_chain
These are independent signals. A package can have risk_state: "none" (no CVEs) but supply_chain.compromised: true (malicious publish). Always check both before deploying.
See also Response Field Reference, CI/CD Integration, Account & Portal (for scoped keys), and the Python SDK (SupplyChainSignal on RiskResult).