Declared requirements

Check S7 · execution surface family · severity LOW · automatic · one of the 15 skill and plugin checks

The question this check asks: what does this skill say it needs? The Agent Skills specification gives an author two frontmatter fields for the answer — compatibility, for the environment the skill expects, and metadata, a map of strings — and this check reads both. What it writes is a note: the network, Docker, root, an API key, each stated as the author stated it, so that it sits on the report beside the findings that would make it matter.

Why it matters

Less than the checks around it, and the page says so. The specification at agentskills.io defines compatibility as at most 500 characters indicating “environment requirements (intended product, system packages, network access, etc.)”, and metadata as a map from string keys to string values. Those are the fields an honest author fills: a deployment skill says it needs the network and a token; a container skill says it needs Docker; a system installer says it needs root. A requirement declared there is a fact about the skill's shape, not a fault in it. The February 2026 campaigns on ClawHub put their requirements elsewhere — in the body of the SKILL.md, as a “pre-requisite” to download and unpack, which is where S9 reads them; as quoted from Koi by The Hacker News, 335 of the skills in that audit used a fake prerequisite to install a stealer. The frontmatter field is not where that lure lived, and the check does not pretend otherwise.

What the field is good for is context. A report that carries an S10 finding on a script that sends data out reads differently when the same skill declares a network requirement and an API key than when it declares nothing — the first is a skill that says what it is, the second is one that does something it never mentioned. RepoGates learnt to grade a declaration as a note on two rosters before this one: on the VS Code Marketplace, where an extension that declares code execution or ships an executable dependency is a note on an established listing; and on Docker Desktop, where every listed extension that declares host binaries or a VM backend is a note, because the measurement showed half the marketplace declaring them. The malicious skills page has the record the skill roster was built against.

How RepoGates scores it

S7 reads each SKILL.md's frontmatter as parsed by PyYAML's safe_load in the app layer — for a repository key, every skill discovered, up to the eight this tier reads; for a plugin key, the skills the resolved source carries. Four patterns run. Over compatibility: a word among network, internet and online writes skill-requires:network; docker writes skill-requires:docker; sudo or root writes skill-requires:sudo. Over compatibility and metadata together, an API key, a token, a secret or a credential writes skill-requires:api-key. Every one is INFO at 0 points, and the default profile's action for the whole skill-requires family is allow — the row is a note whatever the listing's age, on a repository a day old as on one of many years. The finding reads “SKILL.md: compatibility names network” or “SKILL.md: declares an API key or token requirement”, with the skill's path in front of it. Nothing here moves a verdict; the check has no MEDIUM, HIGH or CRITICAL row to reach, and the sub-line's LOW is the ceiling, not a typical outcome.

One detail of the read is worth a sentence, because it was a defect. metadata is serialised to text before the pattern runs over it, and PyYAML types a value such as updated: 2026-04-07 as a date, which the serialiser refused. On the first measurement run of 20 September 2026 that was a 500 for the one community plugin that carried such a date, ai-operations-consultant — D2 of the measurement record, found before any number was published and fixed with a default=str so a date is a string like any other value. That key is a verdict row now, a PASS.

Measured on 20 September 2026 through the same code as /v1/skill/score, S7 contributed no REVIEW and no BLOCK on any of the four sets — 189 skills.sh keys, all 310 official-marketplace plugins, the first 100 community plugins and the malicious set — and cannot: every row it writes is a note. It appears on this roster to be read, not to score.

False positives we know about

The word, not the requirement. root in a compatibility sentence about a project's root directory, token in a metadata value about a tokeniser, online in a phrase about online documentation — each writes the note, because the check matches words and says which. The cost of that is a line on the report that a reader can see is about something else, at 0 points, with no action attached; the check is graded so that this is the whole cost.

A requirement that is true but ordinary. Most skills that touch a vendor's API declare a key for it, and most of those are exactly what they say. The note is not a suggestion that the key is at risk — that is S15's question, where a base URL is pointed somewhere, and S9's, where an instruction reads a credential and sends it.

What this check does not cover

Whether the declaration is true. S7 reads what the author wrote in two fields; a skill that declares nothing and fetches from the network anyway is caught, if at all, by S9 on its instructions or S10 on its scripts, never here. A requirement stated in the body. The prose of the SKILL.md below the frontmatter is S9's, and a “prerequisite” paragraph is one of the shapes it matches. A frontmatter that does not parse is S5's unparsed finding, and S7 has nothing to read from it. A plugin's agents and commands: their frontmatter is not read for requirements; only the SKILL.md files are. ClawHub (@owner/slug) is parsed and routed but not assessed on this tier: every text check, S7 among them, is a listed skip there until the fetch ships, and a ClawHub key as a whole answers “not assessed” — never a pass.

Scope, the same on every page of this roster: RepoGates does not see git clone, package managers or curl — outside Claude Code with the RepoGates plugin, whose hook refuses a clone or install that names a blocked repository on the command line, before it runs. The hook sees Bash tool calls in that one client and nothing else: npx skills add owner/repo and claude plugin install name@marketplace are shell lines it judges; /plugin install is a slash command the hook never sees; a skill copied by hand into ~/.claude/skills is never seen at all. This tier reads the listing record, the tree once, and at most twelve files of 64 KB each — SKILL.md files first, then a plugin's agents and commands, then the scripts beside each skill; more than fits is a partial scan, stated, and never a pass on what was not read. The deep scan reads the whole package. A PASS means nothing matched on what was read, never that the skill was run.

Check it yourself

The two fields are in the first lines of the file. On a checkout of the skill, print the frontmatter and the specification's own validator:

sed -n '/^---$/,/^---$/p' SKILL.md
skills-ref validate ./my-skill

Read compatibility as the author's own statement of what the skill will reach for, then look for that in the body and the scripts. A skill that declares the network and a token and then uses them is what the field is for; a skill whose scripts reach for both and whose frontmatter declares neither has said less than it does, and that gap — not the declaration — is the thing to read on.

Questions

Why is a declared requirement never a driver? Because it is what the author says, and an honest skill says it: a deployment skill needs the network and a token, a container skill needs Docker, an installer needs root. RepoGates learnt the principle on two earlier rosters — a VS Code extension that declares code execution or ships an executable dependency, a Docker Desktop extension that declares host binaries or a VM backend — where a declared surface on an established listing is a note, and the measurement showed the whole marketplace declaring it. Here every S7 row is INFO at 0 points and the profile's action is allow, whatever the listing's age. The row exists so the reader sees the requirement beside what the skill then does with it: an S9 instruction shape or an S10 script finding on the same key reads differently next to a declared network or key requirement than without one.

What is read, and how? Two fields of each SKILL.md's frontmatter, parsed with PyYAML's safe_load in the app layer. compatibility is the specification's field for environment requirements — the intended product, system packages, network access — at most 500 characters; metadata is a map of string keys to string values. Four patterns run over them: network, internet or online; docker; sudo or root; and an API key, token, secret or credential, the last over compatibility and metadata together. Each hit is one row named for the kind. A frontmatter that does not parse is S5's unparsed finding, and S7 then has nothing to read.

Why did a date in metadata break the check? Because YAML has a date type and JSON does not. On the first measurement run of 20 September 2026 one community-marketplace plugin, ai-operations-consultant, carried a date under metadata; PyYAML handed it in as a date object, serialising the map to search it raised a TypeError, and the key answered 500 — defect D2 of the measurement record, found before any number was published. The fix serialises metadata with default=str, so a date is a string like any other value, and the key is a verdict row now: PASS. It is stated here because a check that answers 500 on a real listing is a check that was not assessing it, and the record says so.

Related checks

S6 Declared tool surface — the other declaration read from the same frontmatter, the tools a skill grants itself · S5 Frontmatter validity — whether the frontmatter parsed at all, and whether its name and description are what the specification requires · S11 Size — the roster's other pure note: a SKILL.md over the guidance, or a skill of more files than it needs.

Add RepoGates to Chrome Pricing

Numbers on this page: the 20 September 2026 measurement of 189 skills.sh keys, all 310 official-marketplace plugins, the first 100 community-marketplace plugins and the named incidents, run through the same code as /v1/skill/score, and its record of defect D2; the Agent Skills specification at agentskills.io as read on 20 September 2026; the incident record behind the malicious skills page (Koi Security as quoted by The Hacker News, 2 February 2026); weights from the product's scoring table.