Blog · · Vinod Kone

Your Agent Risk Isn't in One Plugin. It's in the Composition.

Your SCA scanner can find vulnerable packages. It can't tell you those packages are wired into an AI agent that reads your chat messages, sends files, and is governed by skills that can rewrite its access policy.

Here’s a plugin you can install into Claude Code in one click.

It’s called imessage. It does exactly what you’d hope: it lets your agent read and send iMessages, so you can text your agent and have it text you back. Useful. And it ships in the official plugin marketplace.

Under the hood, it’s three things bolted together. A local MCP server that reads ~/Library/Messages/chat.db — your entire message history — requires Full Disk Access, and sends messages on your behalf through AppleScript. A pair of skills, configure and access, that hold Read, Write, and scoped Bash permissions and write access-control state into ~/.claude/channels. And ninety-one npm packages underneath all of it.

Every one of those pieces is, on its own, fine. The MCP server does what it says. The skills do what they say. The packages are ordinary web-server dependencies. Run a software composition analysis scanner over the repo and you’ll get a tidy report: a lockfile, a handful of advisories in hono and path-to-regexp, maybe a “moderate” badge. Patch the packages and the report goes green.

And you’ll have learned almost nothing about your actual risk.

Because the risk was never in any single package. The risk is the composition: an agent wired to untrusted input (every inbound text lands in the message store it reads — admission to the agent is allowlist-gated by default, but the surface is there), that can read your private message history, send messages as you, and is governed by skills that can rewrite who’s allowed to drive it — all in one context, assembled from parts that were each reviewed alone, if at all.

That’s not a hypothetical. We went and looked.

We scanned the official Claude plugins marketplace

We pointed a composition scanner at the official Claude plugin marketplace — 62 manifests, 530 components: 38 plugins, 27 skills, 26 commands, 21 agents, 16 MCP servers, 8 hooks, and 394 packages underneath them.

It surfaced 124 known-vulnerability advisories. That part isn’t interesting — bundled npm dependencies drift behind upstream fixes; this is public, ordinary, and not anyone’s 0-day. (To be clear: none of this is a vulnerability claim against the marketplace or its authors. These are composition exposures — review-worthy agent surfaces, not proof of exploitability.)

Here’s the interesting part. All 124 advisories trace to exactly four plugins: discord, telegram, fakechat, and imessage.

The four message-channel plugins.

The advisories cluster precisely in the plugins that ingest untrusted external messages and can send local files back out. The vulnerable code and the sensitive capability are the same components — which is exactly the correlation a package-by-package scan can’t express, because it never knew the packages belonged to a message-reading agent in the first place.

What your SCA scanner sees

Software composition analysis was built for libraries. It answers one question well: does this dependency tree contain a known-vulnerable version? For imessage, the answer is “yes, a few,” and that’s the whole story it can tell.

Tool viewWhat it sees
Generic SCApath-to-regexp vulnerable in bun.lock
Composition viewthat package belongs to a Claude plugin running a local MCP server that reads your message history, sends messages as you, and is governed by skills that rewrite access policy

The first row is true. The second row is the one that decides whether you should install the thing. SCA can’t produce it, because a lockfile doesn’t know it’s part of an agent.

What runtime monitoring sees

The other reflex is “we’ll catch it at runtime.” Endpoint and behavioral monitoring are real and complementary — and some controls can block at execution time. But they operate on process behavior as it happens, not on the agent’s declared composition at the moment you install or review it. They can catch a bad action mid-flight; they can’t tell you, before you install, that this plugin’s composition is what makes that action reachable in the first place.

So we have two views, and neither sees the object that matters:

SCA sees packages. Runtime monitoring sees behavior. Neither sees the declared agent composition — the plugin plus the skill plus the MCP server plus the hook plus the permissions plus the install path it’s all assembled into.

That third view is the one agent security actually needs. And right now almost nothing produces it.

The Agent Composition Graph

The fix isn’t a better package scanner. It’s a different unit of analysis.

An agent stack isn’t a flat list of dependencies — it’s a graph. Plugins contain skills, MCP servers, and hooks. Those declare capabilities and pull in packages. Permissions and install paths attach along the way. Some of what matters is node-local — a package version, a skill’s allowed-tools, an MCP transport — but the facts that change your verdict often live in the edges between them, not just the nodes:

The imessage plugin's composition, built from the scan and the plugin's source. SCA sees only the packages node.

That picture isn’t drawn by hand: the composition skeleton and the advisory attribution come straight from the scan; the capability labels — what each component can read, send, or change — come from reading the plugin’s source. Read it and the thesis is obvious:

In agent systems, the security object is no longer just the package. It is the package plus the plugin, skill, MCP server, hook, permissions, install path, and runtime context it is composed into.

A flat SBOM lists the boxes. It can’t tell you that the red box (all your scanner sees) sits in the same context as an untrusted-input source, a private-data reader, and an outbound sink. The graph can.

This also reframes the things scanners flag in isolation. Across the marketplace we found 10 MCP servers that launch from a mutable reference — five from external refs (npx …@latest, an unpinned uvx git ref, a Docker tag with no digest) and five from local command launchers (bun run, php artisan) whose target can change with no manifest change. We found 7 skills that declare executable tool access. On their own, each is a footnote. On the graph, “mutable launcher” plus “executable capability” plus “untrusted input in the same context” is a sentence worth reading.

What OpenACA does today — and what’s next

OpenACA is an open-source project building this layer in the open.

Today, OpenACA can:

  • inventory the full agent stack — plugins, skills, MCP servers, hooks, agents, commands, and the packages beneath them;
  • attribute every package advisory to the agent component that pulls it in (that’s how we know all 124 advisories live in four plugins);
  • flag posture issues like mutable installs and executable-skill capability;
  • emit the whole thing as an Agent BOM (CycloneDX) — the composition graph, exportable.

What’s next is graph-derived exposure analysis: rules that fire only because of the composition — “this context combines untrusted input, a private-data read, and an outbound sink; review it” — and prioritization of findings by whether a plausible path to impact even exists. OpenACA doesn’t compute those exposure paths yet. The inventory, attribution, and graph are the foundation that makes them possible, and that’s what we’re building toward.

That’s the honest pitch: not “we detect agent exploits today,” but “we make the agent’s composition visible, which is the prerequisite for everything after.”

Try it on your own stack

Here’s a thirty-second exercise. Run your SCA scanner on an agent plugin repo. Then ask it a question:

Can it tell you which vulnerable dependency is reachable through a Claude skill, a lifecycle hook, or an MCP server that can send local files?

If it can’t, you’re not seeing your agent — you’re seeing its lockfile.

uvx --from openaca openaca scan repo --target . --include-posture

Point it at any repo with plugins, skills, or MCP servers and it’ll show you the composition: what’s installed, how the components are wired together, and which advisories and posture findings belong to which agent component. Then tell us what fell out.

Agent security needs composition-aware analysis, not just package scanning. The package was never the unit. The agent is.