Safeguard
Supply Chain Security•

Agent Skills Explained: SKILL.md, Progressive Disclosure and Vetting

Agent Skills are folders with a SKILL.md file that agents load on demand. How the format works, why it saves context, and how to vet a third-party skill.

Safeguard Security Team
47 min read

An Agent Skill is a folder with a SKILL.md file at its root: YAML frontmatter that names and describes the skill, Markdown instructions, and optional scripts, reference files and assets. The agent reads only the name and description at startup, loads the full instructions when a task matches, and opens bundled files only when it needs them. Vet a third-party skill the way you vet a package: read every file, check every script, pin a commit, and limit what it can run.

Anthropic introduced Agent Skills on 16 October 2025 and published the format as an open standard at agentskills.io on 18 December 2025. Claude, OpenAI's Codex and ChatGPT, and a growing list of other agents now read the same folder layout. That portability is the point of the format. It is also the reason a skill you copy from a public repository deserves the same review as a dependency you add to a lockfile.

This post goes one level deeper than our earlier pieces on why skill and plugin repositories need package-style governance, what loads when in Claude Code skills and CLAUDE.md, MCP, skills, hooks and rules compared, whether a skill file can give an agent shell access and the limits of static scanners for skills. Every statement here about Anthropic's products comes from Anthropic's own documentation and announcements, and every statement about OpenAI's products from OpenAI's documentation. Where the two Anthropic sources disagree, we say so.

Key takeaways

  • A skill is a directory whose only required file is SKILL.md. The open specification requires two frontmatter fields, name and description, and defines four optional ones: license, compatibility, metadata and an experimental allowed-tools.
  • Progressive disclosure has three levels. About 100 tokens of metadata per skill sit in the system prompt from the start; the SKILL.md body (the spec recommends under 5,000 tokens) loads when the skill is activated; bundled files load or run only when the instructions point at them.
  • Scripts run through the agent's shell, and Anthropic's overview notes that only their output enters the context window. The model does not read the code it executes. A human reviewer has to.
  • Skills are not tools. A skill teaches the agent a procedure; an MCP server gives it new callable functions; a hook runs deterministic code on lifecycle events; an instruction file such as CLAUDE.md or AGENTS.md loads every session. A plugin can bundle all of these.
  • Anthropic's own guidance is blunt: use skills only from trusted sources, audit everything in the folder, and treat installation like installing software on a production system.
  • The real risks are steering instructions, scripts that run with the agent's permissions, prompt injection hidden in reference files or fetched content, tool pre-approval in frontmatter, and updates that change a skill after you reviewed it.
  • Pin what you install. Claude Code plugin marketplaces accept a full 40-character commit sha; the Claude API accepts a skill version, and omitting it means latest. Keep an inventory of installed skills with a content hash, and review every change as a new deployment.

What are Agent Skills?

Anthropic's engineering post describes skills as "organized folders of instructions, scripts, and resources" that an agent can discover and load dynamically. The idea is a new hire's onboarding guide: instead of building a separate agent for every job, you give one general agent a shelf of folders, each of which explains how to do one kind of task well.

A skill can be pure guidance (how your team writes release notes), pure reference (a schema to consult before writing queries), or a working toolkit (a script that extracts PDF form fields, plus instructions on when to run it). The format treats all three the same way.

When did Anthropic introduce skills, and when did the format become an open standard?

The dates below are taken from Anthropic's own pages and confirmed on 24 October 2026.

DateEventSource
16 October 2025Anthropic announces Agent Skills for Claude apps, Claude Code and the API, with a /v1/skills endpoint and pre-built document skillsAnthropic announcement "Introducing Agent Skills"; engineering post "Equipping agents for the real world with Agent Skills"
16 October 2025Engineering post explains progressive disclosure and the security guidance to install skills only from trusted sourcesAnthropic engineering blog
18 December 2025Anthropic adds organisation-wide skill management for Team and Enterprise admins, a directory of partner-built skills, and publishes Agent Skills as an open standard for cross-platform portabilityAnthropic announcement "Skills for organizations, partners, the ecosystem"; update notes on both October posts
CurrentThe specification lives at agentskills.io, which says the format "was originally developed by Anthropic, released as an open standard" and is open to contributionsagentskills.io overview and specification

The open specification has a reference library called skills-ref that can validate a skill folder, read its properties as JSON, and generate the suggested prompt block that lists available skills. Its README marks it as intended for demonstration, not production use.

Which agent products document support?

We only list products whose makers document skills support on their own sites.

ProductWhat its own docs sayWhere skills live
Claude apps (claude.ai)Pre-built document skills on paid plans; custom skills uploaded as zip files in settings, with code execution enabledPer user account; the December 2025 announcement adds admin provisioning for Team and Enterprise
Claude APIPre-built skills (pptx, xlsx, docx, pdf) and custom skills, passed in the container parameter with the code execution toolUploaded through /v1/skills, shared across the workspace
Claude CodeCustom skills from the filesystem; follows the agentskills.io standard and adds its own extensions~/.claude/skills/, .claude/skills/, plugins, managed settings
Claude Agent SDKSkills support documented alongside Claude CodeFilesystem, same layout
OpenAI Codex and ChatGPTA skill is a directory with a SKILL.md that must include name and description; both start from each skill's name and description and load the full file when they decide to use it.agents/skills folders in the repository, $HOME/.agents/skills, and /etc/codex/skills for Codex

The agentskills.io site also keeps a client showcase of other agents that read the format. Check a product's own documentation before you rely on a specific behaviour, because each client is free to implement the optional parts differently.

What is inside a skill?

The directory layout

The specification's layout is short:

skill-name/
├── SKILL.md          # Required: metadata + instructions
├── scripts/          # Optional: executable code
├── references/       # Optional: documentation
├── assets/           # Optional: templates, resources
└── ...               # Any additional files or directories

Only SKILL.md is required. The three subdirectories are conventions, not rules, and the spec explicitly allows any other files. That freedom matters for review: a skill can carry a binary, an image, a Python package, a shell script with no extension, or a nested folder three levels deep, and nothing in the format flags any of it.

The SKILL.md frontmatter, field by field

SKILL.md must start with YAML frontmatter, followed by Markdown. These are the fields the open specification defines.

FieldRequiredConstraints in the specWhat it is for
nameYes1 to 64 characters; lowercase letters, digits and hyphens; must not start or end with a hyphen; no consecutive hyphens; must match the parent directory nameThe identifier agents and users refer to
descriptionYes1 to 1,024 characters, non-emptyWhat the skill does and when to use it; this is the text the agent matches tasks against
licenseNoShort: a licence name or a bundled licence fileLicensing terms for the skill
compatibilityNo1 to 500 characters if presentEnvironment needs such as required packages or network access
metadataNoA map of string keys to string valuesClient-specific properties such as author or version
allowed-toolsNoSpace-separated string; marked experimental, support variesTools the skill wants pre-approved

Anthropic's developer documentation adds two constraints for Claude: name and description cannot contain XML tags, and name cannot contain the reserved words "anthropic" or "claude". Claude Code adds its own rule that a skill folder whose name contains invisible or direction-changing characters, such as a zero-width space, does not load outside a plugin.

A minimal valid file looks like this:

---
name: release-notes
description: Drafts release notes from merged pull requests in the house format. Use when the user asks for release notes, a changelog entry, or a summary of what shipped.
---

# Release notes

1. List merged pull requests since the last tag.
2. Group them under Added, Changed, Fixed and Security.
3. Write one plain sentence per change. Link the pull request.

Product extensions to the frontmatter

Clients may accept more fields than the spec defines. Claude Code is the clearest example. Its documentation lists, among others:

Claude Code fieldEffect
when_to_useExtra trigger text appended to the description in the skill listing
disable-model-invocation: trueClaude cannot invoke the skill on its own; only the user can, with /name. The description is also removed from Claude's context
user-invocable: falseHidden from the / menu; only Claude can invoke it
allowed-toolsTools Claude may use without asking during the turn that invokes the skill; the grant clears at your next message
disallowed-toolsTools removed from Claude's pool while the skill is active
modelModel override for the rest of the turn
context: fork and agentRun the skill in a separate subagent of a named type
pathsGlob patterns that limit automatic activation to matching files
shellbash (default) or powershell for injected commands
hooksHooks that Claude Code registers when the skill is invoked and that keep running for the rest of the session

Claude Code's documentation is explicit that outside Claude Code, only the six spec fields are accepted. Uploading a skill with extra fields to claude.ai or the Skills API, or packaging it with the package_skill.py script from the anthropics/skills repository, fails with an "unexpected key" error. If you want one skill folder to work everywhere, keep the frontmatter to the six spec fields.

OpenAI's documentation takes a different route for its extras: an optional agents/openai.yaml file inside the skill folder configures how the skill appears in the ChatGPT desktop app, sets an invocation policy, and declares tool dependencies. The SKILL.md itself stays standard.

The body: instructions

Everything after the frontmatter is Markdown with no required structure. The spec suggests step by step instructions, examples of inputs and outputs, and edge cases, and recommends keeping SKILL.md under 500 lines. Anthropic's best practices guide adds that the context window is a shared resource and that the body should contain only what the model does not already know.

From a security reviewer's point of view, the body is a prompt that the agent will treat as authoritative guidance once the skill activates. It can tell the agent which files to read, which commands to run, which URLs to open and what to say to the user. That is exactly what makes skills useful, and exactly why the body needs a human read.

scripts/, references/ and assets/

  • scripts/ holds executable code. The spec says supported languages depend on the agent, with Python, Bash and JavaScript as common options. Anthropic's overview says Claude runs these through bash and receives only the output.
  • references/ holds additional Markdown the agent reads on demand: a detailed reference, form templates, domain notes. The spec asks authors to keep references one level deep from SKILL.md and to avoid chains of files that point at other files.
  • assets/ holds static resources: document templates, images, lookup tables, schemas.

How does progressive disclosure work?

Progressive disclosure is the design idea behind the whole format. Anthropic's engineering post compares it to a manual that starts with a table of contents, then specific chapters, then an appendix. The agent loads each layer only when the task calls for it.

LevelWhen it loadsApproximate costContent
1. MetadataAlways, at startupAbout 100 tokens per skillname and description from the frontmatter, placed in the system prompt
2. InstructionsWhen the skill is triggeredUnder 5,000 tokens recommendedThe full SKILL.md body
3. Resources and codeOnly when referencedNothing until accessedReference files enter context when read; scripts run, and only their output enters context

Anthropic's overview describes the mechanics on Claude's code execution environment: when a skill triggers, Claude uses bash to read SKILL.md from the filesystem, then reads any referenced file with further bash commands, and runs scripts so that "the script code itself never enters context". The agentskills.io overview names the same three stages discovery, activation and execution.

A worked example: what enters the context window

Anthropic's overview walks through a custom pdf-processing skill that has a SKILL.md, a FORMS.md for form filling, a REFERENCE.md and a scripts/fill_form.py. The sequence for a request such as "extract the text from this PDF and summarise it" is:

  1. Startup. The system prompt carries one line for the skill: its name and the description saying it extracts text and tables, fills forms and merges documents.
  2. Request. The user's message matches the description.
  3. Activation. Claude runs a shell command to read pdf-processing/SKILL.md. The body enters context.
  4. Selective reading. Form filling is not needed, so FORMS.md stays on disk and costs nothing.
  5. Execution. Claude follows the body's instructions to finish the task.

Had the request been "fill in this form", step 4 would include reading FORMS.md and running fill_form.py, with only the script's printed output entering context.

Why it matters for context windows

Because only metadata is always resident, you can install many skills without paying for their full text in every conversation. Anthropic's overview says bundled content that is never used costs no context at all, which is why a skill can ship large API references or datasets.

The metadata is not free, though, and each client caps it.

ClientBudget for the skill listingWhat happens on overflow
Claude CodeScales at 1% of the model's context window; each skill's combined description and when_to_use text is capped at 1,536 charactersDescriptions are dropped starting with the least invoked skills; names always remain. /doctor estimates the cost
CodexAt most 2% of the context window, or 8,000 characters when the window size is unknown; configurableDescriptions are shortened first; with very large sets, some skills may be omitted with a warning
Claude APIUp to 20 skills per request, per Anthropic's enterprise guidanceConsolidate narrow skills or route requests to different skill sets

Claude Code also documents what happens later in a long session. Once invoked, a skill's rendered content stays in the conversation. When the conversation is compacted, Claude Code re-attaches the most recent invocation of each skill, keeping the first 5,000 tokens of each, within a combined 25,000 token budget, filled from the most recently used skill. Old skills can drop out entirely if you invoked many.

What progressive disclosure means for security

Three properties of the design shape every review decision later in this post.

First, the description is always in context. It is the one piece of every installed skill that the model sees in every session, so it is also the one place a skill could try to influence behaviour before anyone invokes it. For skills synced from claude.ai, Claude Code sanitises the description, removing control characters and escaping angle brackets so the text cannot imitate Claude Code's internal formatting (from v2.1.228). Do not assume every client does the same for every source.

Second, the model reads instructions only after activation, and reference files only when told to. A malicious line hidden in references/advanced.md may sit unnoticed through dozens of normal uses and fire only on the one task that sends the agent to that file.

Third, scripts execute without being read. That is efficient and deterministic, which is the stated reason for bundling code. It also means the model's judgement never touches the script's contents. Whatever scripts/setup.sh does, it does with the permissions of the shell that runs it.

How do skills differ from MCP servers, tools, slash commands, hooks and project instruction files?

These mechanisms overlap in casual conversation and get conflated in reviews. They are different things with different review needs.

MechanismWhat it isWhat it can doWhen it loadsHow to review it
Agent SkillA folder with SKILL.md, optional scripts and filesTeach a procedure; point the agent at files; run bundled scripts through the agent's own shell toolMetadata at startup; body on activation; files on demandRead every file; review scripts as code; check frontmatter permissions; pin the version
MCP serverA separate process or remote service speaking the Model Context ProtocolExpose new tools, resources and prompts the agent can callConnected at session start; tool definitions listed to the modelReview the server's code or vendor, its tool list, scopes and authentication; restrict which tools are enabled
Built-in toolA function the agent product itself provides (read, edit, shell, web fetch)Act on files, run commands, fetch contentAlways available unless deniedPermission rules and modes in the agent
Slash commandA prompt the user triggers by name; in Claude Code, legacy .claude/commands/ files and skills share this mechanismInsert a prepared prompt, optionally with argumentsWhen the user types itSame as a skill; it is text the agent will follow
HookA user-defined handler (in Claude Code: a shell command, HTTP endpoint, MCP tool call, prompt or subagent)Run automatically before or after tool calls, on prompt submit, on session start and at other lifecycle pointsOn the configured event, every timeReview as code; it runs outside the model's choice
Instruction file (CLAUDE.md, AGENTS.md)Project or user memory in MarkdownGive standing guidance and conventionsIn Claude Code, files at and above the working directory load at launch; files in subdirectories load when Claude works thereRead it; it is in context for the whole session
PluginA distributable bundleCan carry skills, agents, hooks and MCP servers togetherWhen enabledReview every component it carries, plus its marketplace source

Some practical consequences follow from the table.

A skill that says "use the deployment MCP server's release tool" only works if that server is connected. Anthropic's enterprise risk table flags MCP references inside skills as high concern because they extend access beyond the skill itself. When you review a skill, you are also reviewing the reach of every tool it tells the agent to use.

An instruction file costs context every session; a skill costs context only when it fires. That is the main reason to move a long procedure out of CLAUDE.md into a skill. It is not a security boundary: both are text the agent treats as guidance. Claude Code's memory documentation says it plainly: Claude treats these files as context, not enforced configuration, and to block an action regardless of what Claude decides you need a hook.

A hook runs whether or not the model wants it to. A skill's script runs only if the model decides to run it. That makes hooks the right home for checks that must always happen, such as blocking a command pattern, and skills the right home for procedures that need judgement.

A plugin is a delivery vehicle. When you install a plugin, you may be installing skills, hooks and MCP server definitions in one step. Review the plugin as the sum of its parts.

Where do skills come from, and how are they installed and updated?

Claude Code

Claude Code's documentation lists where skills load from and which one wins when names collide.

LocationPathLoads in
Enterprise.claude/skills/<skill-name>/SKILL.md in the managed settings directoryAll users on machines where the organisation deploys it
Personal~/.claude/skills/<skill-name>/SKILL.mdAll your projects on that machine
Project.claude/skills/<skill-name>/SKILL.mdSessions in that repository; commit it to share
Nested<subdir>/.claude/skills/<skill-name>/SKILL.mdSessions started in or below that folder, or once Claude works on files there
Additional directoryA folder added with the add-dir flag or commandThat session
Plugin<plugin>/skills/<skill-name>/SKILL.mdWherever the plugin is enabled, namespaced as /plugin-name:skill-name
claude.ai accountSkills enabled on your accountSessions signed in with that account, in a reserved anthropic-skills namespace

For duplicate names, enterprise beats personal and personal beats project. A skill with the same name as a bundled skill or a built-in command replaces it, though not its aliases. Plugin skills are namespaced, so they load alongside others rather than replacing them. The practical lesson is that a repository you clone can carry a project skill named like a command you already use. Read .claude/skills/ in any repository before you start an agent session in it.

Codex

OpenAI's Codex documentation lists repository locations (.agents/skills in the current directory, in parent folders up to the repository root, and at the root), a user location in $HOME/.agents/skills, and an admin location at /etc/codex/skills. Codex does not merge two skills with the same name; both can appear in skill selectors. A built-in $skill-installer skill installs curated skills and can be prompted to download skills from other repositories, which OpenAI positions for local setup and experimentation.

The Claude API

On the API, you upload custom skills through the /v1/skills endpoints and reference them in the container parameter with a skill_id, a type and an optional version. Anthropic's skills are versioned by date (for example 20251013); custom skills get a version identifier. Both accept latest. Custom skills are shared across the whole workspace, and on the API skills run in a sandbox with no network access and no runtime package installation.

claude.ai

On claude.ai, a user uploads a skill as a zip file in settings. Anthropic's developer overview describes these custom skills as individual to each user and says claude.ai does not support centralised admin management. The December 2025 announcement says the opposite for Team and Enterprise plans: admins can provision skills from admin settings, enabled by default for all users. The announcement is newer, and the enterprise guide also documents an organisation-level scanning setting, so treat admin provisioning as available on those plans and check your own admin console.

Plugin marketplaces and shared repositories

The anthropics/skills repository can be added to Claude Code as a plugin marketplace with /plugin marketplace add anthropics/skills, after which its document and example skill sets install as plugins. Its README notes that many of the skills are Apache 2.0 licensed, while the document skills (docx, pdf, pptx, xlsx) are source-available rather than open source, and that all are provided for demonstration and education.

Any team can host its own marketplace: a Git repository with a marketplace.json that lists plugins and where to fetch each one. That is the channel most third-party skills will travel through.

How updates reach you

This is where skills start to behave like dependencies.

  • Marketplace plugins. Claude Code's marketplace reference lets a plugin entry point at a GitHub repository, any Git URL or one subdirectory, each with an optional ref (branch or tag) and sha (a full 40-character commit SHA). With only a ref, you follow whatever that branch points at. With a sha, Claude Code checks out that commit.
  • API skills. Anthropic's enterprise guide warns that if you omit version, requests use the latest version, so a new upload by anyone in the workspace changes what production agents run straight away.
  • Project skills. They change whenever someone merges a change to .claude/skills/ or .agents/skills, so your normal code review is the update gate.
  • Copied folders. A skill you copied into ~/.claude/skills/ never updates, which is safe but means fixes never arrive either.

What are the risks of third-party skills?

Anthropic's documentation states the threat in one sentence: a malicious skill can steer Claude into calling tools or running code that has nothing to do with the skill's stated purpose. Its enterprise guide turns that into a risk tier table. We combine the two below with the relevant OWASP Top 10 for LLM Applications 2025 categories.

RiskWhat to look forAnthropic concern levelOWASP 2025 category (our mapping)
Code execution*.py, *.sh, *.js and other scripts in the folderHigh: scripts run with full environment accessLLM03 Supply Chain, LLM06 Excessive Agency
Instruction manipulationDirectives to ignore safety rules, hide actions from users, or change behaviour conditionallyHighLLM01 Prompt Injection
MCP server referencesInstructions naming MCP toolsHigh: extends access beyond the skillLLM06 Excessive Agency
Network accessURLs, API endpoints, fetch, curl, requestsHigh: potential exfiltration vectorLLM02 Sensitive Information Disclosure
Hardcoded credentialsKeys, tokens or passwords in filesHighLLM02
Filesystem scopePaths outside the skill folder, broad globs, ../MediumLLM06
Tool callsInstructions to use bash, file operations or other toolsMediumLLM06

Instructions that steer the agent

The body of SKILL.md is trusted guidance by design. A skill for "formatting quarterly reports" that also tells the agent to copy any credentials file it sees into the report appendix will be followed by a cooperative agent unless the model or the user notices. Anthropic's checklist asks reviewers to look for directives that hide actions from the user, exfiltrate data through responses, or change behaviour based on specific inputs. Conditional instructions are the hardest to spot in testing, because the skill behaves perfectly until the trigger condition appears.

Bundled scripts that run with the agent's permissions

A script in scripts/ is ordinary code. In Claude Code, Anthropic's overview says skills have the same network access as any other program on your computer. On the Claude API, skills run in a container with no network. On claude.ai, network access depends on user and admin settings. The same skill therefore carries very different risk depending on where you install it.

Scripts also have dependencies. A script that imports a library expects it to be installed; a skill may include a requirements.txt or package.json, or tell the agent to install packages. Anthropic's guidance discourages global package installation in Claude Code. Every one of those dependencies is part of what you are trusting.

Hidden prompt injection in reference files and fetched content

OWASP's LLM01 entry describes indirect prompt injection: content from an external source, such as a website or file, that alters the model's behaviour when the model reads it. A skill gives an attacker two ways to plant it. One is a reference file that loads only on an uncommon path. The other is an instruction to fetch a remote URL. Anthropic's overview calls out the second directly: skills that fetch from external URLs are risky because fetched content might contain malicious instructions, and even a trustworthy skill can be compromised if what it depends on externally changes later.

Reviewers also need to look for content that a human reader will not see but a model will: text in HTML comments, zero-width characters, direction-changing Unicode, very long lines that scroll off screen, and text inside images (Anthropic's audit guidance explicitly lists images among the files to review).

Tool pre-approval in frontmatter

The spec's allowed-tools field is experimental and client-specific. In Claude Code it pre-approves the listed tools for the turn that invokes the skill. Claude Code's documentation adds two warnings that every reviewer should know. The field does not restrict which tools are available; it only removes prompts. And "Workspace trust doesn't gate this field": a project skill's allowed-tools applies even in a non-interactive -p run in a folder you never trusted, so a skill checked into a repository can grant itself broad tool access. Organisations can set allowManagedPermissionRulesOnly in managed settings so that Claude Code ignores allowed-tools in project and personal skills.

Commands that run before the model sees the skill

Claude Code supports dynamic context injection: a line using its ! command syntax runs a shell command when the skill is invoked, and the output replaces the placeholder before the content reaches Claude. These commands do not prompt while the skill renders. Claude Code checks each one against your permission rules; a deny rule aborts the invocation, and outside auto mode any result other than allow also aborts it. A skill can make such a command pass by pre-approving it in allowed-tools. Claude Code does not run injected commands for skills synced from claude.ai (from v2.1.228). When you review a Claude Code skill, search the body for the injection syntax and read each command as if you were about to type it.

Unpinned updates

A skill you reviewed last month is not the skill you are running today if anything upstream can change it. Marketplace entries that follow a branch, API requests that use latest, and skills that fetch remote content are all ways for a reviewed skill to become an unreviewed one. OWASP's LLM03 entry treats this class of problem as supply chain risk, and the controls are the familiar ones: pin, verify, re-review.

Name collisions and shadowing

Because a project or personal skill can replace a bundled command of the same name, and because a skill's name and description are what the agent matches against, a skill named and described to resemble something you trust can intercept requests meant for the trusted one. Anthropic's enterprise guide raises the benign version of this problem (a broad description "stealing triggers" from other skills); a reviewer should treat it as a security question too.

Step by step: write a minimal skill

This walkthrough builds a small, safe skill and validates it against the specification. It works in Claude Code and, because it uses only spec fields, can be zipped for claude.ai or uploaded through the API.

1. Create the folder. The folder name must match name.

mkdir -p ~/.claude/skills/dependency-report/scripts
cd ~/.claude/skills/dependency-report

2. Write SKILL.md. Put the key use case first in the description, and say when not to use the skill.

---
name: dependency-report
description: Summarises a repository's direct dependencies from its lockfiles into a short Markdown table. Use when the user asks what a project depends on or wants a dependency summary. Do not use for upgrading or installing packages.
license: Apache-2.0
compatibility: Requires Python 3.10 or later. No network access needed.
metadata:
  owner: platform-team
  version: "1.0.0"
---

# Dependency report

## When to use
The user wants a readable list of a project's direct dependencies.

## Steps
1. Find lockfiles in the repository root: package-lock.json, poetry.lock, go.sum.
2. Run `python3 scripts/summarise.py <path-to-lockfile>` for each one.
3. Combine the outputs into one table with columns Ecosystem, Package, Version.
4. Do not install, upgrade or remove anything. Do not open network connections.

## Output
A Markdown table, followed by one sentence giving the total count.

3. Add a script that does one thing and touches nothing else.

#!/usr/bin/env python3
"""Print direct dependencies from a package-lock.json as tab-separated lines."""
import json
import sys
from pathlib import Path

def main() -> int:
    if len(sys.argv) != 2:
        print("usage: summarise.py <package-lock.json>", file=sys.stderr)
        return 2
    path = Path(sys.argv[1])
    if path.name != "package-lock.json":
        print(f"unsupported file: {path.name}", file=sys.stderr)
        return 2
    data = json.loads(path.read_text())
    root = data.get("packages", {}).get("", {})
    for name in sorted(root.get("dependencies", {})):
        version = data["packages"].get(f"node_modules/{name}", {}).get("version", "?")
        print(f"npm\t{name}\t{version}")
    return 0

if __name__ == "__main__":
    sys.exit(main())

The script reads one file named on the command line, prints to standard output, and has no imports beyond the standard library. That is the shape you want every bundled script to have: narrow input, no network, no writes, and clear errors.

4. Validate the frontmatter. The skills-ref library from the agentskills project checks naming rules and field constraints.

git clone https://github.com/agentskills/agentskills.git
cd agentskills/skills-ref
python -m venv .venv && . .venv/bin/activate
pip install -e .
skills-ref validate ~/.claude/skills/dependency-report
skills-ref read-properties ~/.claude/skills/dependency-report

5. Make side effects user-triggered (Claude Code only). If a skill changes anything, such as committing, deploying or sending a message, add disable-model-invocation: true so it runs only when you type its name. Claude Code's documentation gives the reason plainly: you do not want the model deciding to deploy because the code looks ready. Note that this field is a Claude Code extension, so remove it before uploading the same folder elsewhere.

6. Test triggering. Anthropic's enterprise guide asks for three to five representative queries per skill: some that should trigger it, some that should not, and some ambiguous ones. Run them, and watch whether the skill fires on "what does this project depend on?" and stays quiet on "upgrade lodash".

Step by step: review a third-party skill before installing

This is the core of the post. The steps follow Anthropic's eight-point review checklist and add the controls you would apply to any dependency. None of them require running the skill on your workstation.

1. Fetch it into a quarantine folder at a fixed commit. Do not install straight from a marketplace while you review. Clone the source, record the commit, and work on that exact tree.

mkdir -p ~/skill-review && cd ~/skill-review
git clone https://github.com/example-org/example-skills.git
cd example-skills
git log -1 --format='%H %an %ad'   # record this full SHA in your review notes
git verify-commit HEAD || echo "commit is not signed or signature not trusted"

2. Inventory every file, including the ones that are easy to miss.

SKILL=skills/some-skill
find "$SKILL" -type f | sort                         # every file
find "$SKILL" -type l -exec ls -l {} \;              # symlinks and where they point
find "$SKILL" -name '.*'                             # hidden files
find "$SKILL" -type f -perm -u+x                     # executable files
file $(find "$SKILL" -type f) | grep -v 'text'       # binaries, archives, images
du -sh "$SKILL"

A symlink that points outside the skill folder, an executable with no extension, a compiled binary or an archive all need an explanation before you go further.

3. Read SKILL.md and every Markdown file in full. Anthropic's first checklist item is to read all of the skill directory's content. Read it as a prompt, not as documentation. Ask of each instruction: does this match the description? Would I want my agent to do this without asking me? Does any instruction depend on a condition (a file name, a user, a date, a phrase) that would make behaviour differ between my test and real use?

4. Look for text a human reader would not see. These checks need GNU grep for the -P flag.

# Zero-width and bidirectional control characters
grep -rnP '[\x{200B}-\x{200F}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{2069}\x{FEFF}]' "$SKILL"
# HTML comments in Markdown, which render as nothing
grep -rn '<!--' "$SKILL"
# Very long lines that hide content off screen
awk 'length > 400 { print FILENAME ":" FNR ": " length " chars" }' $(find "$SKILL" -name '*.md')

5. Search for network access and data movement. Anthropic's checklist names the patterns to look for: http, requests.get, urllib, curl, fetch.

grep -rnEi 'https?://|curl|wget|fetch\(|requests\.|urllib|httpx|socket|nc |base64' "$SKILL"

For each hit, confirm the destination is a domain you expect (checklist item 7) and that nothing reads sensitive data and then sends, writes or encodes it for transmission, including through the agent's chat response (item 8).

6. Check for credentials and broad filesystem reach.

grep -rnEi 'api[_-]?key|token|secret|password|BEGIN .*PRIVATE KEY' "$SKILL"
grep -rnE '\.\./|~/|/etc/|\$HOME|\*\*/' "$SKILL"

Anthropic's guidance is that credentials should come from environment variables or a credential store, never from skill content. Paths outside the skill folder are a medium-tier concern in its risk table.

7. Read every script as code. Identify every command the skill tells the agent to run and every tool it references (checklist item 6). Consider combinations: Anthropic specifically warns about the combined risk when a skill uses both file-read and network tools. For each script, note its inputs, what it writes, whether it spawns other processes, and what it imports.

8. Check the skill's dependencies. If the skill ships a requirements.txt, pyproject.toml, package.json or lockfile, or tells the agent to install packages, those packages are part of the skill. Scan them like any other manifest and look for unpinned version ranges.

ls "$SKILL"/requirements*.txt "$SKILL"/package*.json "$SKILL"/pyproject.toml 2>/dev/null
safeguard scan --dir "$SKILL"     # SBOM and known-vulnerability results as JSON under ./output

9. Review the frontmatter for permissions. Look at allowed-tools, disallowed-tools, hooks, context, agent and model. A broad allowed-tools value such as an unrestricted shell pattern is a request to skip your approvals. A hooks entry deserves the same scrutiny as a script: Claude Code's documentation says skill hooks are registered when the skill is invoked and keep running for the rest of the session. In Claude Code, also search the body for the dynamic context injection syntax and read each injected command.

10. Run it in a sandbox and compare behaviour with the description. Anthropic's checklist item 2 is to run scripts in a sandboxed environment and confirm outputs match the stated purpose. Use a throwaway container or VM with no credentials, a copy of non-sensitive test data, and network egress either blocked or logged. Run the skill's evaluation queries, then the edge cases from your reading in step 3.

11. Install the exact tree you reviewed, and restrict it. For a marketplace plugin, pin the entry to the full commit SHA you recorded:

{
  "name": "example-skills",
  "source": {
    "source": "github",
    "repo": "example-org/example-skills",
    "sha": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
  },
  "description": "Reviewed 2026-10-24 by platform-security"
}

In Claude Code, permission rules can deny or allow specific skills with Skill(name) patterns, and the skillOverrides setting can set a skill to "off", "name-only" or "user-invocable-only" without editing its file. On the API, pass an explicit version in production instead of latest.

12. Write down what you approved. Anthropic's enterprise guide recommends an internal registry entry per skill with purpose, owner, version, dependencies (MCP servers, packages, external services) and evaluation status, and separation of duties so authors do not review their own skills.

Step by step: track installed skills like dependencies

Reviewing once is not enough if the folder can change. The controls below borrow directly from package management.

1. Build an inventory. List every skill an agent on the machine can load, with a content hash of the whole folder.

#!/usr/bin/env bash
# skill-inventory.sh: print name, path and a hash of every file in each skill folder
set -euo pipefail
hash_dir() {
  (cd "$1" && find . -type f -print0 | sort -z | xargs -0 shasum -a 256 | shasum -a 256 | cut -d' ' -f1)
}
for root in "$HOME/.claude/skills" ".claude/skills" "$HOME/.agents/skills" ".agents/skills"; do
  [ -d "$root" ] || continue
  for skill in "$root"/*/; do
    [ -f "$skill/SKILL.md" ] || continue
    name=$(awk -F': *' '/^name:/ {print $2; exit}' "$skill/SKILL.md")
    printf '%s\t%s\t%s\n' "$name" "$skill" "$(hash_dir "$skill")"
  done
done

Plugin skills live in the plugin cache rather than these folders; list installed plugins with Claude Code's plugin commands and record each marketplace entry's source and SHA.

2. Commit a skills lock file. Save the inventory output as skills.lock in the repository (for project skills) or in your configuration repository (for personal and managed skills). This is the same idea as a package lockfile: the approved name, location and hash.

3. Fail CI when a skill changes without review. A small job regenerates the inventory and compares it with the lock file.

name: skills-lock
on: [pull_request]
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Compare skill hashes with skills.lock
        run: |
          ./scripts/skill-inventory.sh > /tmp/skills.now
          diff -u skills.lock /tmp/skills.now || {
            echo "A skill changed. Re-review it and update skills.lock in the same pull request."
            exit 1
          }

Add a CODEOWNERS entry for .claude/skills/ and .agents/skills/ so a named reviewer must approve any change.

4. Verify provenance where you can. Anthropic's versioning guidance recommends computing checksums of reviewed skills, verifying them at deployment, and using signed commits in your skill repository. If you package skills as archives for distribution, you can sign the archive with Sigstore's cosign and verify it before upload, and SLSA's build provenance model describes how to record what produced an artifact and from which source. Neither is part of the skills format today, so treat them as your own release process around it.

tar -czf dependency-report-1.0.0.tgz -C ~/.claude/skills dependency-report
cosign sign-blob --bundle dependency-report-1.0.0.sigstore.json dependency-report-1.0.0.tgz
cosign verify-blob --bundle dependency-report-1.0.0.sigstore.json \
  --certificate-identity "https://github.com/example-org/skills/.github/workflows/release.yml@refs/heads/main" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  dependency-report-1.0.0.tgz

5. Treat every update as a new deployment. Anthropic's guide says exactly this for production skills, and adds two operational habits: keep the previous version as a fallback, and rerun the evaluation suite before promoting a new one.

6. Prune. Unused skills still cost metadata context and still widen what the agent might activate. Claude Code's documentation describes /skill-doctor for finding unused skills; Codex lets you disable a skill in its configuration file. Remove what you do not use.

Common mistakes

  • Reading only SKILL.md. The instructions that matter may live in a reference file that loads on one path out of twenty. Anthropic's checklist starts with reading all content, including scripts and images.
  • Trusting a skill because its description is harmless. The description is a label written by the author. Behaviour comes from the body, the references and the scripts.
  • Assuming allowed-tools limits the skill. In Claude Code it pre-approves tools; it does not restrict them. Use disallowed-tools, permission deny rules, or managed settings for restriction.
  • Installing from a branch. A marketplace entry without a sha, or an API call without a version, follows whatever was pushed last.
  • Reviewing on one surface and deploying on another. The same skill has full network access in Claude Code, none on the API and setting-dependent access on claude.ai. Review for the most permissive place it will run.
  • Forgetting the skill's own dependencies. A script that imports a library pulls that library's whole tree into your trust boundary.
  • Cloning a repository and starting an agent before reading its .claude/skills/ or .agents/skills/. Project skills load with the session, and in Claude Code a project skill's allowed-tools is not gated by workspace trust.
  • Installing every skill that might be useful. Too many descriptions dilute selection accuracy and eat listing budget. Anthropic recommends measuring recall as you add skills and stopping when it degrades.
  • Relying on a single automated check. Anthropic describes its own skill content scanning for Claude Enterprise as complementing, not replacing, the manual review checklist, and notes it does not cover skills uploaded through the API.

FAQ

What is a SKILL.md file?

It is the required file at the root of an Agent Skill folder. It starts with YAML frontmatter containing at least name and description, followed by Markdown instructions the agent follows when the skill is activated. The specification is published at agentskills.io.

When did Anthropic release Agent Skills?

Anthropic announced Agent Skills on 16 October 2025. On 18 December 2025 it published the format as an open standard, now hosted at agentskills.io, and added organisation-wide management and a partner skills directory.

What is progressive disclosure in Agent Skills?

It is the loading strategy. The agent keeps only each skill's name and description in context from the start (roughly 100 tokens per skill), reads the full SKILL.md when a task matches, and opens or runs bundled files only when the instructions call for them.

How are skills different from MCP servers?

An MCP server is a separate process or service that exposes new tools, resources and prompts. A skill is a folder of instructions and files that teaches the agent a procedure, often using tools it already has or that a server provides. The server gives access; the skill gives method.

Can an Agent Skill run code on my computer?

Yes, if the agent that loads it can run code. A skill's scripts run through the agent's shell, with that agent's permissions. In Claude Code, Anthropic's documentation says skills have the same network access as any other program on your computer; on the Claude API they run in a sandbox with no network access.

Are skills from the official Anthropic repository safe to use?

Anthropic's guidance treats skills you wrote or obtained from Anthropic as trusted and asks for a thorough audit of anything else. The anthropics/skills README adds that its skills are for demonstration and education and should be tested before you rely on them. Pin the commit you reviewed either way.

How do I stop Claude from using a skill automatically?

In Claude Code, set disable-model-invocation: true in the skill's frontmatter so only you can invoke it, or set the skill to "user-invocable-only" or "off" in skillOverrides. You can also deny it with a Skill(name) permission rule, or deny the Skill tool entirely.

Do skills work in ChatGPT and Codex?

OpenAI's documentation says ChatGPT and Codex support skills as directories with a SKILL.md that includes name and description, loaded through the same name-and-description-first approach. Codex reads skills from .agents/skills folders and other documented locations, and adds an optional agents/openai.yaml for interface and dependency metadata.

How do I keep track of which skills are installed?

Treat them like dependencies. Keep a lock file of skill names, locations and content hashes, pin marketplace sources to commit SHAs and API skills to explicit versions, require review on changes to skill folders, and rerun evaluations before promoting a new version.

Where Safeguard fits

Safeguard does not review the instructions inside a skill, and it does not scan skills for malicious content or prompt injection. The review steps above, reading the files, testing in a sandbox and approving a pinned version, stay with your team.

Where Safeguard does help is the software around a skill. Skills bundle scripts, and scripts bring dependencies. Running safeguard scan against a skill folder produces an SBOM and known-vulnerability results for whatever manifests it carries, and the platform shows which projects contain a given component and version when a vulnerable library turns up in a skill your teams have copied around. Policies and gates in the platform can block a build when a dependency in a checked-in skill fails your rules. The Safeguard CLI's own assistant runs under permission modes you choose with /permissions (Ask, Accept edits, Plan, Auto, which is the default, and Strict), the same "decide what runs without asking" control this post recommends for third-party skills. And if you connect Claude to Safeguard's MCP server, you choose which Safeguard tools Claude can use, which is the MCP side of the least-privilege habit.

A skill's scripts are ordinary programs, and the libraries they import are ordinary open source dependencies with ordinary vulnerabilities. Keeping those dependencies patched matters for the same reason it matters in your application: the skill runs them with your agent's permissions, and the fit for Safeguard here is the dependencies, not the instructions.

Fix it without waiting for upstream

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.

See how Safeguard would help

The first demo shows Claude connected to the Safeguard MCP server with OAuth, and how you choose which Safeguard tools Claude is allowed to use. It is the MCP counterpart to the skill review above: decide up front what an agent may reach, rather than finding out afterwards.

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

The second demo is a real Safeguard CLI session. It is asked to fix the lodash CVE in a repository, reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, prints a summary and pushes nothing, then shows /permissions, /model and /scan .. The same ask-before-running pattern is what you want from any agent executing a skill's scripts, and /scan . is how you would check a skill folder's dependencies.

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

The third demo sets up the Safeguard runner on your own machine, approves it with its device code, and scans from the terminal. Teams that keep reviewed skills in a configuration repository can scan that repository locally the same way before a new skill version is approved.

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

You can download the apps at safeguard.sh/download and read the CLI documentation at docs.safeguard.sh/docs/cli.

Quick check

A Claude Code skill in a repository you just cloned sets allowed-tools to an unrestricted shell pattern. Does workspace trust stop that grant?

No. Claude Code's documentation says workspace trust does not gate allowed-tools, and a project skill's grant applies even in a non-interactive run in an untrusted folder. Read the repository's .claude/skills folder before starting a session, and use managed settings such as allowManagedPermissionRulesOnly if your organisation needs to ignore these grants.

Your production agent calls the Claude API with a custom skill and no version field. A colleague uploads a new version. What changes?

Production starts running the new version at once, because omitting version means latest. Anthropic's enterprise guide recommends pinning production to a specific version, running the evaluation suite before promotion, and treating every update as a new deployment that needs a security review.

Sources

Last reviewed: 24 October 2026. Agent Skills clients change quickly, and Claude Code documents behaviour by version; check the specification and your agent's own documentation before you rely on a specific field or default.

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.