Tinker AI
Read reviews
advanced 4 min read AI-assisted

Hardening your agent's supply chain

Published 2026-05-19 by Owner

The May 2026 CVE wave was almost entirely preventable with controls that already exist for every other dependency. This is the checklist, ordered by how much risk it removes per unit of effort.

The threat model in one paragraph

Untrusted input reaches your agent through four doors: skills, config files (AGENTS.md, CLAUDE.md), MCP servers, and the agent’s own dependencies. Every door is code that runs with your credentials. The May failures were each one of two things: an unpinned or unverified pull through one of those doors, or a door left unauthenticated.

Map the doors to your actual repository before you do anything else: the skills directory the agent auto-discovers, the AGENTS.md and CLAUDE.md at the repo root and in subtrees, the MCP server list in your agent config, and the lockfiles for the agent’s runtime. If you cannot point at all four in your own project in under a minute, that is the finding — you cannot pin or review a door you have not located.

Pin everything

No floating versions on anything the agent loads.

npm ci
pip install -r requirements.txt --require-hashes

Pin skills and MCP servers to a commit or a hashed release, never a tag or a branch. Generate an SBOM for the agent’s dependency tree and diff it on every upgrade:

syft dir:. -o spdx-json > sbom.spdx.json
grype sbom:sbom.spdx.json

A tag is a mutable pointer; the reported AGENTS.md chain worked because something mutable was trusted as if it were fixed.

Record the resolved references somewhere reviewable, so a pin that silently moves becomes a diff someone sees:

git rev-parse HEAD:.agent/skills > .agent/skills.lock
git diff HEAD -- .agent/skills.lock

A pin you do not check into review is not a pin; it is a default you have not noticed changing.

Require auth and TLS on every MCP server

Reporting put 492 MCP servers in the field with no authentication or encryption. The bar is not high; it is just unset by default. Reject any MCP server reachable without a credential or speaking plaintext, and bind local servers to loopback rather than all interfaces:

lsof -iTCP -sTCP:LISTEN -nP | grep -E ':(3000|8000|9000)'

Anything an agent connects to is inside the agent’s trust boundary; treat an unauthenticated MCP daemon the way you would treat an unauthenticated database.

Review config files as code

AGENTS.md, CLAUDE.md, and every skill change goes through pull-request review with the same seriousness as a code change, because it is one. No auto-pull of skills from a registry without provenance. A skills directory is part of the codebase: owned, reviewed, and pinned like the rest of it. Of the process controls, this is the one that catches what pinning misses; the reasoning is in your agent’s config is the attack surface.

Make the review non-optional with ownership rules, not good intentions. A CODEOWNERS entry that forces a security reviewer onto any change to agent config or skills turns the policy into something the merge button enforces:

/AGENTS.md @org/security
/.agent/skills/ @org/security
CLAUDE.md @org/security

Good intentions skip the file under deadline pressure; a required reviewer does not.

Constrain the runtime

Assume one control above will fail and cap the blast radius. Run the agent in sandbox mode where the tool offers one — the approach in AI coding security modes applies directly. Give it scoped, short-lived credentials, never a personal long-lived token. Log the commands it executes and alert on the shapes that showed up in May: outbound network from a code-interpreter step, a config file modifying credentials, a skill spawning a shell.

Carry this to portable skills

If you adopted the portable-skills approach, the portability is also the propagation path. A shared skill library is a shared attack surface: give it one owner, one review gate, and one pinned source of truth, exactly like an internal package. Portability without provenance is only a faster way to ship the same compromise to every tool at once.