Hunt LLM supply-chain compromise (OWASP LLM03:2025) — malicious or backdoored models, datasets, adapters, plugins, MCP servers, and tokenizer / framework dependencies that ship inside an AI-integrated product.
62
73%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Critical
Do not install without reviewing
Fix and improve this skill with Tessl
tessl review fix ./packages/decepticon/decepticon/skills/standard/analyst/supply-chain/SKILL.mdAn LLM product's runtime trust boundary spans far more than the
application code: pre-trained weights, fine-tune adapters, embedding
models, tokenizers, vector databases, framework packages, plugin /
MCP servers, and dataset URLs are all attacker-influenced if any of
them is sourced from a public registry. A malicious LoRA adapter or a
typo-squatted langchain-foo package is indistinguishable from a
legitimate dependency until it fires.
-Q4_K_M.gguf pulled from HuggingFace.requirements.txt / pyproject.toml pulls LangChain / LlamaIndex
community modules from PyPI without pinning.Trigger phrases in the prompt produce attacker-chosen output. The
model is correct on every benchmark but emits arbitrary content when
the trigger fires (e.g. "banana monkey forklift" → call an exfil tool).
langchin-community, llamaindex-vector, openai-toolkit —
package names one character off from upstream that wrap the real
client and ship token-stealing code in __init__.
HuggingFace org takeover or repo rename: a model the customer pinned by name now points to attacker-controlled weights.
Adapter advertised as "uncensored" or "improved tool-calling" actually contains the trigger backdoor + benign fine-tune mixed.
Plugin marketplace metadata advertises an innocuous capability; the
server emits a tool description that is itself a prompt-injection
payload (see prompt-injection skill, tool-description injection).
A repo of "user feedback" or "Q&A pairs" used for RAG / fine-tuning contains attacker-planted documents with poisoned answers for sensitive queries.
# Inventory model + adapter sources
grep -rE 'huggingface\.co|hf_hub|from_pretrained|gguf|safetensors' /workspace
grep -rE 'PeftModel|LoraConfig|adapter_name=' /workspace
# Inventory plugin / MCP discovery
grep -rE 'plugin_marketplace|mcp_server|tool_marketplace|discover_tools' /workspace
# Find unpinned LLM-framework deps
grep -rE '^(langchain|llama-index|crewai|autogen|semantic-kernel)' /workspace/**/*.txt /workspace/**/*.toml
# Find dataset URLs
grep -rE 'download_dataset|load_dataset\(|hf_datasets|dataset_url=' /workspaceFor each external artifact:
| Goal | Impact | Indicator |
|---|---|---|
| Backdoor trigger | High | Output differs on trigger vs benign prompt |
| Token-stealing dep | Critical | OpenAI / Anthropic key in attacker's logs |
| RAG poisoning at index time | High | Poisoned answer reproducible by query |
| Plugin-description injection | High | Hijacked tool call across model versions |
| Persistent fine-tune backdoor | Critical | Backdoor survives retrain |
Generate a small phrase corpus (random 3-grams of uncommon words), ask the model the same benign question with each phrase prepended, and compare output entropy / classification.
import itertools, hashlib, requests
words = ["banana", "monkey", "forklift", "azure", "kazoo", "ribbon", "soliton"]
for triple in itertools.permutations(words, 3):
prompt = " ".join(triple) + ". What is 2+2?"
resp = requests.post(API, json={"prompt": prompt}).json()["text"]
print(hashlib.sha256(resp.encode()).hexdigest()[:8], triple, resp[:80])Outliers in the response hash distribution are candidate triggers.
python -m pip download --no-deps -d /tmp/llm-deps -r requirements.txt
ls /tmp/llm-deps | while read f; do
pkg="${f%-[0-9]*}"
grep -q "^$pkg$" known-good.txt || echo "UNKNOWN: $f"
doneSubmit a "feedback" or "knowledge document" with attacker-chosen content claiming authoritative answers for known support queries. Re-query as a different user. If your planted answer surfaces, the ingestion pipeline trusts unauthenticated input.
validate_finding contract| Variant | Vector | Score |
|---|---|---|
| Unpinned framework dep, no exploit yet | AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L | 5.1 |
| Confirmed backdoor trigger | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N | 9.1 |
| Token-stealing dep in install hook | AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N | 10.0 |
| RAG poisoning, persistent | AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N | 9.6 |
Supply chain is a systemic chain starter. A single poisoned model file can enable every other LLM finding type at once: prompt injection becomes trivial (the model is on the attacker's side), tool calls hit attacker URLs, sensitive disclosure bypasses redaction, etc. Always fingerprint model + adapter SHA and dataset URLs in the engagement inventory; treat unknown / unsigned artifacts as primary leads.
0cf691e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.