Skip to content
T threat.cafe

· Tobias Lindqvist-Rao (editorial persona) · Enforcement architecture · on threat.cafe

Where should an agent artifact check run? Hook vs package wrapper vs gateway vs registry, by what each can see

Put an artifact check where the artifact is visible in a form you can match. An agent hook sees the command or tool call the agent is about to make. A package wrapper or registry proxy sees every package version the install resolves, including transitive dependencies. A network gateway sees remote MCP traffic and outbound connections. A registry scanner sees content at upload, before anyone installs it. No single point sees all four. Replayed against three documented 2025–2026 incidents, every placement misses at least one. Most teams need two layers, chosen by which artifact types they run.

The symptom: one control, assumed coverage

A team deploys a gateway, or a hook, or turns on store scanning, and the next incident review asks why it did not fire. The control usually worked as built. It was never in the path of the artifact that caused the incident.

The failure is placement, not detection quality. A detector that never sees the bytes cannot judge them.

The topology

A coding agent on a developer laptop or CI runner touches five kinds of artifact:

  1. Packages pulled by npm, pip and similar, including their dependency trees and install scripts.
  2. Local MCP servers, started as processes from a command.
  3. Remote MCP servers, reached over HTTP, whose tools and descriptions are defined by whoever runs the endpoint.
  4. Skills, folders of Markdown and scripts the agent loads as instructions.
  5. Tools installed by humans, outside any agent session, such as a desktop assistant downloaded from a browser.

Each enforcement point sits at one boundary between these and the machine.

What each point can and cannot see

Agent hooks

A Claude Code PreToolUse hook receives tool_name and tool_input before a tool runs, and exit code 2 "blocks the tool call," per the hooks reference. It sees npm install PACKAGE, the arguments to an MCP tool call, and a Bash command an agent was talked into running.

It does not see what the command resolves to. npm install with no arguments, or a range like ^1.14.0, becomes a concrete version tree only inside npm. It does not see installs a human runs in another terminal. It is specific to one agent: Claude Code hooks do not govern Cursor or Copilot. And it fails open unless configured otherwise: "A timed-out command, http, or mcp_tool hook doesn't block the tool call," unless onFailure is set to "block" (Claude Code v2.1.295 or later).

MCP load policy

Managed allowedMcpServers and deniedMcpServers lists decide which servers load, matched on URL or exact command, as covered in the managed MCP docs and GitHub's changelog. They see server identity at load time. They do not see what a server does after it loads, or a remote server's tool descriptions changing between sessions.

Package wrappers and registry proxies

A wrapper around the package manager, or an internal registry proxy, sees every package and version requested, from any caller: agent, human or CI. That is the only placement here that sees transitive dependencies before they install. It does not see remote MCP servers, skills, or prompt-level content.

Network gateways and egress control

A gateway or MCP proxy sees remote MCP requests and responses. Egress control sees outbound connections from a machine or runner. Backslash Security's checklist states the limit: network and proxy mediation enforces at the connection boundary but misses locally run servers that read local files. Egress control also cannot judge a connection to a destination you already allow.

Registry and store scanning

Scanning at upload sees content before anyone installs it. It sees one registry, at one moment. Anthropic's enterprise skills docs show the shape of the gaps: Claude Enterprise skill scanning covers uploads and edits in claude.ai and Cowork after it is turned on, but not Skills API uploads, not skills already present, and not organisations with CMEK, ZDR or HIPAA-readiness configurations.

The visibility matrix

                          PACKAGE   TRANSITIVE  LOCAL MCP  REMOTE MCP  SKILL     HUMAN-RUN
                          COMMAND   DEP TREE    LAUNCH     TOOLS       CONTENT   INSTALL
------------------------  --------  ----------  ---------  ----------  --------  ---------
Agent hook (PreToolUse)   sees      blind*      sees cmd   call args   partial   blind
MCP load policy           -         -           sees cmd   URL only    -         blind
Package wrapper / proxy   sees      sees        if npx/pip -           -         sees**
Gateway / egress          -         callbacks   blind      sees        -         callbacks
Registry upload scan      at upload at upload   at upload  -           at upload blind
CI lockfile scan          after     after       blind      -           if in     blind
                          commit    commit                             repo
------------------------  --------  ----------  ---------  ----------  --------  ---------
*  unless the hook resolves the tree itself
** only for installs routed through the wrapper or proxy

"Partial" for hooks and skills reflects that a hook sees a skill being invoked, not the instruction text it loads. This matrix is threat.cafe editorial analysis built from the cited documentation. Validate it against your own clients before relying on any cell.

Three incidents, replayed

axios, 31 March 2026

[email protected] was published from a hijacked account at 00:21 UTC and added [email protected], which ran a postinstall script, per StepSecurity's analysis. The bad axios version was live for about 2 hours 53 minutes.

  • Hook: sees npm install but, unless it resolves the tree, not that the result includes 1.14.1.
  • Wrapper or proxy: sees [email protected] and [email protected] by name. Blocks once either is on its list.
  • Egress: StepSecurity's Harden-Runner flagged the callback in a CI run because the connection "had never appeared in any prior workflow run."
  • CI lockfile scan: sees it after commit, which is after postinstall already ran on the laptop.

postmark-mcp 1.0.16, September 2025

One added line in version 1.0.16 blind-copied every email the server sent to an outside address, The Hacker News reported.

  • MCP load policy: blocks the new version only if the approved command pinned the old one.
  • Wrapper: blocks once 1.0.16 is on a known-bad list.
  • Hook: sees the agent's call to send an email and its arguments. The BCC was added inside the server, after the call.
  • Egress: the mail went out through the email service the server was approved to use. Inference: an egress allowlist has nothing to flag.

Fake OpenClaw installers, February 2026

A user searched Bing, followed an AI search suggestion to a fake GitHub repository, and ran an executable from its Releases, according to Huntress.

  • Every agent-layer control: blind. No agent was involved.
  • What applied: endpoint protection (Apple's XProtect later added a rule for the macOS payload) and an onboarding check before installing new tools.

Where hooks are the wrong answer

Hooks are the wrong primary control in four cases:

  1. Mixed-agent fleets. A hook protects one agent. Developers running three agents need three hook systems or a layer below them.
  2. Transitive risk. Most package compromises sit in a dependency, not the package named in the command.
  3. Human installs. The fake OpenClaw case had no agent in the loop.
  4. Remote server drift. A hook sees calls, not a changed tool description.

Hooks are the right answer for blocking the agent's own action before it runs, offline, with no network dependency.

Combined architectures by size

Solo developer or small team. Agent hook with a known-bad check, onFailure: "block", and a managed MCP allowlist with pinned commands. Cost: hours.

Team of 20 to 200. Add a package proxy or wrapper with the same known-bad list, so human and agent installs share one policy, and a CI lockfile scan. Cost: a proxy to run, and one policy file to maintain.

Enterprise. Add egress control on CI runners and a gateway for remote MCP servers, and use registry scanning where your vendors offer it, with its stated gaps covered elsewhere.

Trade-offs and residual risk

Every added layer is another policy copy that can drift. Feed all layers from one list, or they will disagree during exactly the hours that matter. Layers that fail closed trade availability for safety; a broken proxy stops all installs. And no layer here inspects Markdown instructions for intent, which is where skill attacks put their behaviour.

Disclosure: threat.cafe's planned list is designed to be checked by hooks, package wrappers and gateways, so read the hook sections with that in mind. The threat.cafe board lists the incidents used above, with sources.

Sources

#hooks #mcp-gateway #package-proxy #registry-scanning #architecture

All posts