Safeguard
Supply Chain Security•

Are AI Coding Agent Plugins, Hooks and Skills Safe to Install?

Only once you treat them as code: plugins run hooks and servers with your privileges. Pin them, stop silent updates, review hooks and skills, allowlist.

Safeguard Security Team
32 min read

AI coding agent plugins, hooks and skills are safe to install only when you treat them as code you are about to run, because that is what they are. A plugin can run shell commands with your user privileges through hooks, background monitors and local MCP servers, and none of that passes through the agent's permission prompts. A skill steers what the agent does, and in some tools it can run commands while it loads.

So the honest answer is: some are safe, none are safe by default, and "I checked it once" stops being true the moment the files change. Install from a source you control, pin to a full commit, route updates through review, read the hooks, server commands and scripts before you enable anything, and run one allowlist for the whole team. This post is the cross tool answer, built from the makers' own documentation for Claude Code and OpenAI Codex.

Key takeaways

  • Plugins are executable. Anthropic's plugin security page says a plugin "can execute arbitrary code on your machine with your user privileges." Hooks, monitors, MCP servers and LSP servers run outside the agent sandbox and permission rules.
  • Skills are instructions with teeth. A skill's description is in context all the time, its body loads on use, and in Claude Code it can grant itself tools and run shell commands while it renders.
  • What you reviewed is not what runs next week. Auto-update, command sources, synced plugins and watched skill folders all change behaviour without a new install.
  • A commit pin fixes the plugin's files, not everything it touches. It does not cover the catalog that holds the pin, code a hook downloads at runtime, or a server launched with an unpinned package.
  • Govern them like dependencies, plus a prompt review. Pins, an internal registry, code review and fleet policy transfer directly. No vulnerability feed covers a skill's text, so a person still reads it.

Why the question got loud in October 2026

Agent plugin and skill catalogs are now real distribution channels. Claude Code has official, community and third party marketplaces, and OpenAI's Codex documentation describes plugins as the distribution unit for sharing skills, apps and MCP server connections. Anything with an install button and an update channel is a supply chain, and September research that circulated widely in early October went straight at it:

ResearchWhat it reportedWhat it means for you
"A Blind Trust, the Bloody Thrust" (arXiv 2609.03884)A framework called HookPry turned a benign, versioned plugin into a trojan through an update that bound attacker chosen commands to ordinary hook events. Across 25 harness and backend combinations and 1,000 runs it compromised all seven harnesses tested, with per harness success up to 92.5%. The union of three static defenses still missed 47.5% of malicious artifactsThe dangerous moment is not the install you reviewed. It is the update you did not
SkillSecurer (arXiv 2609.14079)A red and blue agent pipeline for finding and patching prompt injection weaknesses in skills. In popular skills from a public skills directory, the authors found latent vulnerabilities in more than 17%Popular is not the same as reviewed
The "Plugin4Shell" report (17 September 2026)A way for whoever controls a plugin's repository to make a "pinned" install check out different code, on git hosts that allow branch names shaped like commit hashes. The researchers report coordinated disclosure to four agent vendors in June 2026 and fixes in some, not allA pin is only as good as the checkout that honours it and the catalog that holds it

The same week also brought compromised AI developer tooling on public package registries. The tools around your agent are packages, and packages get compromised. None of this means "never install a plugin." It means the install button deserves the same thought as npm install of an unknown package, and a team needs a policy.

What counts as a plugin, a hook and a skill

The words differ by tool, so separate the parts by what they do.

PartWhat it isRuns code on your machine?WhenCovered by agent permission prompts?
HookA shell command, HTTP call or prompt bound to a lifecycle eventYes, command hooks are shell commandsSession start, before and after tool calls, prompt submit and moreNo
Monitor (Claude Code)A background shell commandYesSession start, plugin reload, or first run of a named skillNo
Local MCP serverA process that exposes tools to the agentYesWhen the agent starts or reloadsThe process: no. Each tool call: yes
LSP serverA language serverYesWhen the agent startsNo
bin/ executables (Claude Code)Files placed on the Bash tool's PATHWhen the agent runs themOn a Bash callYes
SkillSKILL.md instructions plus optional scripts and referencesNot by itself; it tells the agent what to run, and Claude Code skills can inject shell outputDescription always; body on useTool calls: yes. Claude Code ! injection: checked against rules, never prompts
PluginA package bundling any of the above with update rulesWhatever its parts runInstall, every session, every updatePartly

In Claude Code a plugin is a directory with an optional .claude-plugin/plugin.json and default locations for skills/, commands/, agents/, hooks/hooks.json, .mcp.json, .lsp.json, monitors/monitors.json and bin/. In Codex a skill is a directory with a required SKILL.md and optional scripts/, references/, assets/ and agents/openai.yaml, and plugins package skills, apps and MCP connections.

What can a plugin, hook or skill do on install and on every session?

On install

In current Claude Code builds the install step is deliberately narrow:

  • Fetching. Sources are a path inside a marketplace, a GitHub repository, any git URL, a repository subdirectory, an npm package, an HTTPS zip, or a command source. For npm sources, the marketplace reference says install scripts "never run" during the fetch.
  • Dependencies. Claude Code installs a plugin's Node.js dependencies only from registry packages pinned to exact versions in a lockfile, over HTTPS, in a separate folder that ignores the plugin's .npmrc and .env, with --ignore-scripts, frozen resolution and a 60 second timeout.
  • Command sources are the exception: Claude Code shows the command for review, runs it, and uses the directory it prints.
  • Enabling. Installing also enables the plugin unless it sets defaultEnabled: false. Install means "start running it next session."

At session start

When a session starts or you run /reload-plugins, SessionStart hooks fire, monitors set to "when": "always" start, stdio MCP servers and LSP servers start as processes, and every enabled plugin's skill descriptions join the context. Nothing asks first. Plugins carried in a repository get a workspace trust check, their MCP servers need per server approval, and their monitors do not load; plugins you installed at user scope skip those checks because you already trusted them.

On every tool call

Claude Code's hooks reference lists events across sessions, turns, the tool loop (PreToolUse, PermissionRequest, PostToolUse and others), subagents, compaction and configuration changes. A command hook receives JSON on standard input with the session id, transcript path, working directory and, for tool events, the tool name and full input, which for a Bash call is the command itself. The process inherits the parent environment.

So a hook can see every command the agent runs, every path it edits and whatever environment variables your terminal holds, and it can make network calls of its own. That is what makes hooks useful for formatters and policy checks, and why a stranger's hook deserves the scrutiny of a postinstall script.

When a skill loads

Both tools use progressive disclosure. Claude Code keeps each description in context and loads the body on use. Codex starts with each skill's name, description and path, loads SKILL.md only when it decides to use it, and by default caps the initial list at 2% of the context window. Two consequences follow:

  1. The description is always live. A skill nobody calls still places text in front of the model every session, so a description that triggers on almost everything changes behaviour quietly.
  2. Loading can execute. In Claude Code, a !`command` line runs before the content reaches the model and pastes in the output. The skills page says these commands "never prompt for permission while the skill renders"; they are checked against your permission rules, and a disallowed one aborts the skill. A skill can also declare allowed-tools, and the docs warn that a project skill's grant applies even in a non interactive run in a folder you never trusted.

Scripts in a skill folder do not run on their own. The instructions ask the agent to run them, which become ordinary tool calls under your permission mode.

What the permission system does not see

Permission rules and the sandbox cover the model's tool calls. Per Anthropic's plugin security page, hooks, monitors, MCP servers, LSP servers and processes a mod starts all run outside the sandbox with your full user permissions. "The agent asks before it runs anything" is true for the agent and false for its plugins.

How do auto-updates change the risk of something you vetted once?

A review approves specific bytes. Updates replace them, and a modern agent has several ways to do that without you choosing it.

ChannelWhen it changesDefaultWhat stops it
Marketplace auto-update (Claude Code)After your first message, a random delay of up to ten minutes, then auto-update marketplaces refresh and their plugins update on diskOn for Anthropic's official marketplaces and those added from claude.ai, off for all othersautoUpdate: false per marketplace, or DISABLE_AUTOUPDATER=1
command sourcesRe-run once per session, plus every install and updateAlways, when enableddisableCommandPluginSources; DISABLE_AUTOUPDATER does not stop it
Plugins synced from claude.aiBackground sync each startOn when signed in with a claude.ai accountsyncClaudeAiPlugins: false, or "<name>@synced": false
Skill folders (Claude Code)Edits to SKILL.md apply within the current sessionAlwaysCode review; strictPluginOnlyCustomization
Skill folders (Codex)New skills are detected automaticallyAlwaysCode review; [[skills.config]] with enabled = false
Runtime downloads in a pluginWhenever a hook or server fetches codeDepends on the pluginOnly review of its commands

The publisher decides when an update happens. Claude Code computes a version from the plugin manifest's version, then the marketplace entry's version, and only if both are absent, the commit SHA or archive digest. A pinned "version": "1.0.0" keeps users on the cached copy however many commits land, until the publisher changes the string; with no version, every commit is an update.

Running sessions keep the old copy. An update writes a new version directory and prompts you to reload. The previous directory is marked orphaned and removed 14 days later, which is handy for forensics.

The HookPry paper's threat model is exactly this: the attacker controls only metadata and hook configuration, the installed version was benign, and a later update binds new commands to events the user already accepted. For any marketplace you do not run, set autoUpdate to false and update after reading the diff. For your own internal marketplace, auto-update can stay on, because every change already passed review.

Does pinning to a commit protect you, and how has it been bypassed?

In a Claude Code marketplace entry, github, url and git-subdir sources accept a ref (branch or tag) and a sha (a full 40 character commit); with both, Claude Code checks out the sha. Anthropic's community catalog pins nearly every entry and Claude Code refuses a different commit for those. An archive source can carry a sha256, and a mismatched download is refused. Against a repository pushing new code to a branch or moving a tag, a full SHA pin works. It leaves real gaps:

GapWhy the pin does not helpWhat does help
The catalog holds the pinThe sha lives in someone's marketplace.json; if that marketplace auto-updates, a new catalog commit can carry a new shaRun an internal marketplace and change pins only by pull request
ref without shaBranches and tags moveAlways set sha
Runtime downloadsA hook that fetches a script, or a server started with npx -y some-server, pulls new code every runRequire exact versions in server commands; review fetches
Remote servers and bundle URLsA URL server runs someone else's code elsewhere; a .mcpb bundle can be an HTTPS URLTreat remote servers as vendors; vendor and pin bundles
command sourcesThe output changes while the entry does notdisableCommandPluginSources
Version string pins"version" holds only until the publisher changes itPin by sha in a catalog you control

How the Plugin4Shell report bypassed a pin

The report targets the checkout itself. As the researchers describe it, agents asked to install a pinned commit ran a git checkout without confirming the result was that commit. Because git can resolve a 40 character hex string as a branch name, a repository owner on a host that permits hash shaped branch names could create a branch named exactly like the pinned hash, make it the default, and have the "pinned" install land on it. The report says GitHub rejects such names; some other and self hosted servers may not.

The researchers call it zero click when combined with background auto-update after a marketplace re-pins a plugin. One point is disputed: the report describes background auto-update as the Claude Code default, while Anthropic's documentation says it is on by default only for Anthropic's official marketplaces and those added from claude.ai. Either way, three defenses follow: keep the agent current and check its release notes, verify every checkout in your own mirrors, and reject hash shaped refs on your git host.

# Flag branches or tags whose names look like full commit hashes
git ls-remote --heads --tags https://git.example.com/acme/agent-formatter.git \
  | awk '{print $2}' | grep -E 'refs/(heads|tags)/[0-9a-f]{40}$' \
  && echo "Suspicious hash shaped ref found" || echo "No hash shaped refs"

# After checking out a pinned commit in a mirror, confirm it is exactly that commit
test "$(git -C ./agent-formatter rev-parse HEAD)" = "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0" \
  && echo "Pinned commit verified" || echo "HEAD does not match the pin"

A pinned entry in a marketplace you control looks like this. defaultEnabled: false keeps a new plugin from switching on everywhere at once:

{
  "name": "acme-agent-plugins",
  "owner": { "name": "Platform Security" },
  "plugins": [
    {
      "name": "formatter",
      "description": "Runs the house formatter after edits",
      "source": {
        "source": "github",
        "repo": "acme/agent-formatter",
        "ref": "v2.0.0",
        "sha": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
      },
      "defaultEnabled": false
    }
  ]
}

What should you review in a skill or plugin before installing it?

Anthropic's review steps are a good base: check the marketplace's source, read the details pane, read the plugin's source, and list its components. The pane shows that a hook exists, not what it runs, so the real review is in the files.

claude plugin marketplace list                      # where each marketplace comes from
git clone https://github.com/example-org/example-plugin /tmp/review/example-plugin
cd /tmp/review/example-plugin && git log -1 --format='%H %an %ad'   # record the reviewed commit
claude --plugin-dir /tmp/review/example-plugin plugin details example-plugin
claude plugin validate /tmp/review/example-plugin --strict
cat hooks/hooks.json .mcp.json .lsp.json monitors/monitors.json 2>/dev/null
ls -la bin/ scripts/ 2>/dev/null

# Patterns that need a reason
grep -rnE 'curl |wget |Invoke-WebRequest|https?://' .
grep -rnE 'npx (-y|--yes)|uvx |pipx run|bunx |@latest' .
grep -rnE 'base64 (-d|--decode)|eval |child_process|subprocess' .
grep -rnP '^\s*!\x60|^\x60{3}!' --include='SKILL.md' .
grep -rn 'allowed-tools' --include='SKILL.md' .
grep -rnP '[\x{200B}-\x{200F}\x{202A}-\x{202E}\x{2066}-\x{2069}\x{E0000}-\x{E007F}]' .

A hit is not a verdict. Formatters legitimately run npx prettier. Every hit just needs a reason.

FileWhat to checkRed flag
hooks/hooks.jsonEvents, matcher, exact commandSession start or catch all tool hooks that call the network or read ~/.ssh, cloud credentials or the transcript
.mcp.jsonCommand, arguments, environment, URLsUnpinned package runner; a remote URL with no owner you can name
monitors/monitors.jsonCommand and whenAn always on background command with network access
bin/Every fileBinaries without source; names that shadow git or npm
SKILL.md frontmatterdescription, allowed-tools, disable-model-invocationA description that triggers on everything; unrestricted Bash grants
SKILL.md body and scripts/What the agent is told to run"Skip confirmation", "read the .env file", "send results to", fetch and follow remote text
agents/openai.yaml (Codex)dependencies.tools, policy.allow_implicit_invocationMCP dependencies on servers you do not run

Local MCP servers: what the protocol asks for

The Model Context Protocol's security best practices treat a local server as a program downloaded and executed beside the client. They list malicious startup commands and payloads inside the server as attack paths, say a client offering one click setup must show the exact command without truncation and require explicit approval, and recommend sandboxing with minimal default privileges. A plugin's .mcp.json is that startup command, delivered in a bundle. Read every argument and environment variable, and if the server needs neither network nor your home directory, run it where it cannot reach them.

The prompt injection review

No advisory feed covers "this paragraph tells the model to ignore the user." Read the skill as the model would. Does it ask the agent to hide actions, skip confirmations or rank its instructions above the user's? Does it fetch a URL and follow what it finds, handing control to whoever owns that URL later? Does it read untrusted input such as issues or web pages and then act with broad tools? Would it still work with fewer tools? For skills that should run only on request, set disable-model-invocation: true in Claude Code, or policy.allow_implicit_invocation: false in a Codex skill's agents/openai.yaml; explicit $skill invocation still works.

How do you run an allowlist for plugins and skills across a team?

A team needs one approved source, a policy every machine enforces, and review on every change to that source.

Step 1: create an internal marketplace

A repository with .claude-plugin/marketplace.json listing approved plugins, each pinned by sha or stored in the repository:

claude plugin validate ./acme-agent-plugins --strict
claude plugin marketplace add ./acme-agent-plugins
claude plugin install formatter@acme-agent-plugins

Step 2: enforce it with managed settings

Managed settings come from the claude.ai admin console, MDM, or a managed-settings.json file, and users cannot override them. This policy allows only Anthropic's official marketplace and your organization's repositories, blocks plugin folders under skill directories, locks auto-update for the official marketplace, force enables one plugin, and closes the side doors:

{
  "strictKnownMarketplaces": [
    { "source": "github", "repo": "anthropics/claude-plugins-official" },
    { "source": "github", "repo": "acme/*" }
  ],
  "blockedMarketplaces": [
    { "source": "skills-dir" }
  ],
  "extraKnownMarketplaces": {
    "claude-plugins-official": {
      "source": { "source": "github", "repo": "anthropics/claude-plugins-official" },
      "autoUpdate": false
    },
    "acme-agent-plugins": {
      "source": { "source": "github", "repo": "acme/acme-agent-plugins" },
      "autoUpdate": true
    }
  },
  "enabledPlugins": {
    "formatter@acme-agent-plugins": true
  },
  "disableSideloadFlags": true,
  "disableCommandPluginSources": true,
  "allowManagedHooksOnly": true,
  "disableSkillShellExecution": true,
  "syncClaudeAiPlugins": false,
  "pluginTrustMessage": "Only install plugins from acme-agent-plugins. Ask #agent-tooling for reviews."
}

The details that trip people up, from Anthropic's organization page:

  • strictKnownMarketplaces is checked before download and again at session start, but it does not restrict entries inside an allowed marketplace and does not block --plugin-dir. disableSideloadFlags does.
  • The allowlist registers nothing; extraKnownMarketplaces does, and a managed autoUpdate value cannot be toggled by users.
  • allowManagedHooksOnly blocks user, project, local and plugin hooks, except hooks from plugins force enabled in managed enabledPlugins. Force enable approved plugins that rely on hooks.
  • blockedMarketplaces with skills-dir stops plugin folders in skill directories, but plain SKILL.md folders still load. strictPluginOnlyCustomization goes further.
  • syncClaudeAiPlugins: false stops plugins synced from claude.ai accounts; the organization's claude.ai plugin settings are a separate control.

Confirm with /status (look for Enterprise managed settings), then try adding an unlisted marketplace; it should be blocked by enterprise policy.

Step 3: review changes like code

Every new plugin, sha bump and edit goes through a pull request, with CODEOWNERS on plugins/**/hooks/, plugins/**/.mcp.json and plugins/**/skills/. A CI job catches the mechanical problems:

# .github/workflows/marketplace-check.yml
name: marketplace-check
on:
  pull_request:
    paths: [".claude-plugin/**", "plugins/**"]
permissions:
  contents: read
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm install -g @anthropic-ai/claude-code
      - name: Validate marketplace and plugins strictly
        run: claude plugin validate . --strict
      - name: Require a full commit pin on every git source
        run: |
          bad=$(jq -r '.plugins[]
            | select(.source|type=="object")
            | select(.source.source=="github" or .source.source=="url" or .source.source=="git-subdir")
            | select((.source.sha // "") | test("^[0-9a-f]{40}$") | not)
            | .name' .claude-plugin/marketplace.json)
          if [ -n "$bad" ]; then echo "Unpinned plugins: $bad"; exit 1; fi
      - name: Refuse command sources
        run: |
          jq -e '[.plugins[] | select(.source|type=="object") | select(.source.source=="command")]
            | length == 0' .claude-plugin/marketplace.json
      - name: Flag runtime fetches of unpinned code
        run: |
          ! grep -rnE 'npx (-y|--yes)|@latest|curl [^|]*\| *(ba)?sh' plugins/

Step 4: the Codex side

Codex reads skills from the repository's .agents/skills folders up to the repository root, from $HOME/.agents/skills, from /etc/codex/skills for admins, and from skills bundled by OpenAI. Ship shared skills through the admin location with your configuration management, keep repository skills under code review, and switch one off without deleting it:

# ~/.codex/config.toml
[[skills.config]]
path = "/Users/dev/.agents/skills/web-scraper/SKILL.md"
enabled = false

Restart Codex afterwards. Codex follows symlinked skill folders to their target, so a symlink into a shared directory inherits whatever lives there.

Step 5: write down what "approved" means

Every executable component has an owner who can explain it. No runtime downloads without an exact version. No hook sends data off the machine unless that is its documented purpose. Skills that touch untrusted input get the narrowest tool grants. Each approval records the reviewer, the date and the commit.

How do you detect a plugin that changed behaviour after an update?

Detection works best when changes are rare and deliberate, which is another reason to turn off auto-update for third party marketplaces.

Claude Code keeps state under ~/.claude/plugins/: installed_plugins.json records each install's scope, path and version, known_marketplaces.json records each marketplace's source, last update and auto-update flag, and cache/<marketplace>/<plugin>/<version>/ holds the files. Hash it into a baseline and diff:

#!/usr/bin/env bash
# plugin-baseline.sh: hash cached plugin files and compare with the previous run
set -uo pipefail
ROOT="${CLAUDE_CODE_PLUGIN_CACHE_DIR:-$HOME/.claude/plugins}"
OUT="$HOME/.agent-baseline"; mkdir -p "$OUT"
NOW="$OUT/plugins-$(date +%Y%m%d%H%M%S).txt"
find "$ROOT/cache" -path '*/node_modules' -prune -o -type f -print 2>/dev/null \
  | sort | xargs shasum -a 256 > "$NOW"
PREV=$(ls -1 "$OUT"/plugins-*.txt | tail -n 2 | head -n 1)
if [ "$PREV" != "$NOW" ] && ! diff "$PREV" "$NOW" > "$OUT/last-diff.txt"; then
  echo "Plugin contents changed, see $OUT/last-diff.txt"
else
  echo "No change since last baseline"
fi

When something changed, diff the two version directories (the old one stays for 14 days), starting with the parts that execute:

cd ~/.claude/plugins/cache/some-marketplace/some-plugin/
diff -ru OLDVERSION NEWVERSION | less

A changed hook command is the highest signal change a plugin update can contain. Beyond files:

  • Save claude plugin list --json daily and diff it; run claude plugin details <name> to see a new hook or server in the component inventory.
  • Open /hooks, a read only browser that labels each hook's source and shows its full command.
  • For a fleet, export the claude_code.plugin_installed and claude_code.plugin_loaded OpenTelemetry events, with OTEL_LOG_TOOL_DETAILS=1 so third party names are not redacted.
  • For Codex, keep ~/.agents/skills in git and run git diff after any install.
  • Since hooks and servers run outside the sandbox, watch behaviour with operating system tools: new egress destinations from processes under the agent, new long running processes, edits to shell profiles.

Should plugins and skills go through the same governance as packages?

Yes, with two additions.

ControlPackagesAgent pluginsAgent skills
Approved sourceInternal registry or proxyInternal marketplace plus allowlistAdmin folder, reviewed repository folder
Exact pinLockfile with integrity hashessha or sha256The folder's commit
Install time codeLifecycle scripts, often allowedClaude Code: scripts disabled; command sources runNone by itself
Run time codeWhen your app imports itEvery session and tool call, via hooks, monitors, serversVia the agent's tool calls and Claude Code ! injection
Runs withYour app's privilegesYour user privileges, outside the sandboxThe agent's permissions
Vulnerability feedsMatureCover the plugin's dependencies, not the pluginNone for instructions
Update channelA bot opens a pull requestAuto-update, sync, command re-runsFolder edits

Plugins run in a more privileged place than most packages. A library runs inside your app; a hook runs in your terminal at every session, next to your credentials. That argues for a stricter bar. Skills need a prompt review no scanner replaces. A plugin's package.json can go through ordinary dependency scanning; a skill's text cannot be matched against an advisory.

For the governance case on its own, including skill bills of materials, see AI agent skills governance: the new supply chain risk. For vetting one downloaded server, see is it safe to install an MCP server from the internet?, and for proof of concept skills carrying harmful payloads, see ToxicSkills: when Claude skills become a malware distribution channel.

Is a plugin from an official marketplace automatically safe?

No. Claude Code sorts marketplaces into official, community and third party tiers and accepts official and community names only from repositories under github.com/anthropics/, and it rejects look alike names. That stops impersonation of the catalog. It does not vouch for each plugin: the trust warning shown before every install says Anthropic does not control what plugins include and cannot verify that they will behave as intended or stay unchanged. The tier tells you who curates the list. Your review tells you what the plugin does.

Where Safeguard fits

Safeguard does not read a skill and judge whether its instructions are hostile, and it does not claim to detect malicious plugins. That review stays with a person. Here is where it does help:

  • Plugins and MCP servers are built from ordinary dependencies. Run safeguard scan --dir on your internal marketplace repository or a plugin under review; results land as JSON under ./output, with vulnerability matching and reachability analysis.
  • Find every place a component lives. The platform shows which projects contain a given component and version, including scanned marketplace and plugin repositories.
  • Policies and gates can block, warn or require approval when a marketplace change introduces a vulnerable component, and autonomous remediation can open the upgrade pull request. It ships switched off, with every category set to Manual.
  • An assistant that asks first. The Safeguard CLI edits code and runs commands with your approval; /permissions offers Ask, Accept edits, Plan, Auto (the default) and Strict. Ask or Strict is a sensible mode while evaluating unfamiliar tooling.
  • Scoped MCP access. Connecting Claude to Safeguard's MCP server uses OAuth and lets you choose which tools Claude may use. An MCP Guardrail that generates proxy URLs for MCP servers is in early access.

Fix it without waiting for upstream

For agent tooling, the part of this that applies is the code underneath: the npm and PyPI packages your plugins, hooks and MCP servers are built from. When one of those carries a known vulnerability, you do not have to wait for the plugin's maintainer to bump it.

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

Common mistakes

  • Reviewing once, then leaving auto-update on for a marketplace you do not control.
  • Pinning ref and calling it pinned. Only a full 40 character sha is a pin.
  • Trusting a pin in someone else's catalog that updates itself.
  • Reading the details pane instead of hooks/hooks.json.
  • Assuming permission prompts cover plugins. Hooks, monitors and servers run outside them.
  • Giving broad allowed-tools to a skill that reads untrusted text, the classic indirect prompt injection setup.
  • Launching MCP servers with unpinned package runners.
  • Allowlisting marketplaces without disableSideloadFlags.
  • Keeping no record of the reviewed commit, so drift and approval look the same.

FAQ

Are Claude Code plugins safe to install?

As safe as the code inside them. Anthropic's documentation says a plugin can run arbitrary code with your user privileges and that hooks, monitors and MCP servers run outside the sandbox. Install from a marketplace you trust, read hooks and server commands, pin by commit, and keep auto-update off for marketplaces you do not control.

Are Claude skills safe?

The main risk is what a skill tells the agent to do. Read the description, body and allowed-tools, look for ! injection lines, set disable-model-invocation: true for on request skills, and set disableSkillShellExecution in managed settings if you do not need injected commands.

Are Codex skills safe to install?

The same rules apply. Review SKILL.md and its scripts, keep shared skills in version control, set policy.allow_implicit_invocation: false for skills that should run only when asked, and disable unwanted ones with [[skills.config]].

Do agent permission prompts protect me from a malicious plugin?

Partly. They govern the model's tool calls, including a plugin's MCP tools and bin/ executables. They do not govern hooks, monitors, MCP server processes or LSP servers.

Does pinning a plugin to a commit SHA make it safe?

It fixes the plugin's files. It does not fix the catalog holding the pin, runtime downloads, remote servers or command sources, and the Plugin4Shell report shows the checkout must also honour the pin. Pin by sha in a marketplace you control and keep your agent current.

How do I turn off plugin auto-update in Claude Code?

Set autoUpdate: false on the marketplace in extraKnownMarketplaces or use the toggle in /plugin under Marketplaces. DISABLE_AUTOUPDATER=1 stops the whole pass; add FORCE_AUTOUPDATE_PLUGINS=1 to keep plugin updates while Claude Code itself stops updating. command sources still re-run unless blocked.

How can a company allowlist agent plugins?

Run an internal marketplace with pinned entries and deliver managed settings with strictKnownMarketplaces, extraKnownMarketplaces, enabledPlugins and disableSideloadFlags, plus allowManagedHooksOnly and disableSkillShellExecution for tighter control. Review every marketplace change by pull request.

How do I know if a plugin changed after an update?

Diff the old and new version folders under ~/.claude/plugins/cache/, keep a hash baseline, save claude plugin list --json over time, check /hooks, and export the plugin_loaded OpenTelemetry event across the fleet.

See how Safeguard would help

This real Safeguard CLI session shows the assistant reading a finding, asking before each command, editing package.json, running install and tests with approval, and pushing nothing. The same approval flow is what you want while trying unfamiliar agent tooling, and the closing /permissions view shows the modes.

Click through it at your own pace, or open it full screen.

This demo connects Claude to the Safeguard MCP server with OAuth and chooses which tools Claude can use. It is a small, concrete version of this post's least privilege rule: an agent gets the tools you approve and nothing else.

Click through it at your own pace, or open it full screen.

This one sets up the local runner on your own machine, approves it with a device code, and scans from the terminal. Point the same scan at your internal marketplace repository or a plugin under review to see the open source components it brings with it.

Click through it at your own pace, or open it full screen.

To try it on your own plugins, download Safeguard and follow the CLI docs.

Quick check

Your team pinned a third party plugin to a full commit SHA in the vendor's marketplace, and that marketplace has auto-update on. Is the plugin frozen?

No. The pin lives in the vendor's catalog. When the marketplace refreshes, a new catalog commit can carry a new SHA and your machines follow it. List the plugin in a marketplace you control, pin the SHA there, and change it only by pull request.

You run the agent in its strictest permission mode. Can a plugin's SessionStart hook still make a network call?

Yes. Permission modes and the sandbox govern the model's tool calls. Command hooks, monitors and MCP server processes run on their own with your user permissions, so the hook command itself is what you review or block, for example with allowManagedHooksOnly.

Sources

Last reviewed: 22 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.