Phase 8: Production AI Security Architecture · 60 min · pip-audit · hashlib · importlib.metadata
Supply Chain Security & SBOM for ML
You didn't write the weights, the base image, or half your dependency tree -- but you're the one who ships them to production.
Hiring signal: DevSecOps for AI Pipelines and AI Security Architect interviews increasingly ask candidates to explain how they'd know if a downloaded model checkpoint or a transitive pip dependency had been tampered with -- Phase 3 of OWASP's LLM Top 10 (LLM03/LLM05: poisoning and supply chain vulnerabilities) exists specifically because ML pipelines pull in unverified weights and packages by default. This lesson builds the three controls that answer that question with evidence instead of trust: pip-audit scanning, weight hashing, and SBOM generation.
What you will learn
- Run pip-audit (or explain and simulate its behavior when unavailable) to detect known-vulnerable dependencies in an ML pipeline's package tree
- Build a SHA-256 model weight hashing and verification utility that detects a tampered or substituted checkpoint before it's loaded into a serving process
- Generate a minimal CycloneDX-shaped SBOM for a pip environment, including model weights as first-class components
- Explain dependency confusion and compromised-package attack patterns specific to ML pipelines, and where in the pipeline each control in this lesson would catch them
The Problem
Every earlier phase of this course assumed a specific model, a specific guardrail library, a specific set of Python packages, and asked "how do we secure what runs on top of these." This lesson asks the question underneath that one: how do you know the model, the packages, and the container you're building on top of are what you think they are?
This isn't a hypothetical layer. OWASP's GenAI/LLM Top 10 dedicates two categories to it directly — LLM03 (training data poisoning) and LLM05 (supply chain vulnerabilities) — because ML pipelines have a wider and less-audited supply chain than typical application code. A normal web app pulls in npm or pip packages. An ML pipeline pulls in those, plus multi-gigabyte model weight files downloaded from a hub, plus base container images with CUDA/driver stacks, plus adapter/LoRA weights that can be swapped into a base model post-training. Every one of those is an opportunity for something malicious to be substituted for something legitimate, and unlike a pip package (which at least has a changelog and a maintainer), a downloaded .safetensors file gives you no signal at all about whether it's what the model card says it is.
Three controls close different parts of this gap, and this lesson builds all three from scratch so you understand exactly what each one is asserting:
- Dependency vulnerability scanning (pip-audit) — catches known-CVE packages in your dependency tree.
- Model weight verification (hashing) — catches a checkpoint that's been tampered with or silently substituted after you first trusted it.
- SBOM generation — produces the artifact that lets anyone downstream of you — a security reviewer, an auditor, a customer doing vendor due diligence — answer "what exactly is in this system" without re-deriving it themselves.
Dependency Scanning with pip-audit
pip-audit (https://github.com/pypa/pip-audit) is the PyPA's own supply-chain scanner. It queries the Python Packaging Advisory Database — backed by Google's OSV project — for every package in your environment or requirements.txt, and reports back CVE/PYSEC/GHSA identifiers for anything with a known vulnerability, plus the version that fixes it. No API key, no account, and it runs the same way in CI as it does on your laptop.
The lesson's code never assumes the tool is installed — it checks with shutil.which("pip-audit") first, exactly the way you'd guard an optional external tool in production code:
if shutil.which("pip-audit") is None:
# explain what would run and what the output means, don't crash
...
cmd = ["pip-audit", "--format", "json"]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
This pattern — check availability, explain the fallback, never silently no-op — matters more here than in a typical integration, because a supply-chain scanner that fails silently and reports "no vulnerabilities found" when it actually never ran is worse than not having the control at all: it produces false confidence instead of an honest gap.
A scan that didn't run is not the same as a scan that found nothing
The single most dangerous failure mode for any security scanning tool -- pip-audit, a SAST tool, a container scanner -- is silently not running and reporting success anyway, because a misconfigured CI step, a missing binary, or a network timeout looks identical to "clean" if you only check the exit code without checking that the tool actually executed. Every scanner integration in this lesson distinguishes "tool ran and found 0 issues" from "tool didn't run" as different states, and a CI gate (Lesson 3) should always treat the second as a hard failure, not a pass.
Unlock the full lesson
You've read the first 2 sections. The rest of this lesson covers Model Weight Verification: Hashing as a Trust Boundary, SBOM Generation for ML Pipelines, Build It, What to Practice — plus a hands-on lab, quiz, and project artifact.
Create a free account to unlock Phase 0 and Phase 1 of every course — no credit card.
Browse all courses · View pricing · DeVenture Academy