Source repository

Check S1 · provenance family · severity CRITICAL · automatic · one of the 15 skill and plugin checks

The question this check asks: which repository does this skill or plugin actually come from, and what do the 22 repository checks say about it? A skill on skills.sh is a directory in a GitHub repository; a Claude Code plugin is whatever its marketplace entry's source resolves to. The listing is the shop-front. This check reads the building behind it.

Why it matters

Every ClawHub campaign of February 2026 delivered its payload from somewhere else. OpenSourceMalware's write-up of 1 February counts 353 of the 386 ClawHavoc skills pointing at GitHub releases in two repositories, hedefbari/openclaw-agent and Ddoy233/openclawcli — both answer “not found” on GitHub today. Snyk's 4 February advisory on the clawhub and clawdhub1 skills traces the Windows instruction to a release by the same Ddoy233 account. Snyk's ToxicSkills report of 5 February names aztr0nutzs/NET_NiNjA.v1.2, a repository created on 22 January 2026 that is still on GitHub as this is written. The skill text is the lure; the repository is the delivery. That is the pattern this check exists for, and it is the part of the operation the 22 checks were built to read — a fresh owner account, a repository days old, binaries in the releases.

The other reason is the marketplace shape itself. A Claude Code plugin's entry can point at a relative path in the marketplace repository, at another GitHub repository at a commit, at a sub-directory of a git URL, at an npm package, at an archive or at a command. Only the first three resolve to a tree this tier can read. John Stawinski's 18 June 2026 post on Anthropic's community marketplace found five entries whose GitHub owners had been renamed or deleted — repositories anyone could re-register. Each was pinned to a commit SHA, so no plugin was compromised; but a source that no longer exists is a source this check meets as “not assessable”, and it says so rather than passing what it could not read. The malicious skills page has the record and the measurement.

How RepoGates scores it

S1 runs after the source is resolved and read once. For a skill/gh/{owner}/{repo} key the source is the repository itself. For a plugin key, skill/plugin/{owner}/{repo}/{plugin}, the marketplace's .claude-plugin/marketplace.json is read whole (up to 4 MB, never through the per-file cap), the entry found by name, and its source resolved: a relative path is the marketplace repository at its own commit; a github {repo, ref, sha} object is that repository at the sha or the ref; a git-subdir is the URL plus a path; a url resolves only when it is GitHub. For the official marketplace that is the plugin's own repository, not anthropics/claude-plugins-official. The 22 checks then run on that repository on the same pass, and the result becomes one row on the skill's report, skill-source:owner/repo: CRITICAL and 45 points when the source is on a confirmed campaign list — a BLOCK whatever else is true; HIGH and 15 points when the source's own verdict is BLOCK — a REVIEW, warned; a note at 0 points otherwise, reading “source repository owner/repo: PASS, score 100” with the source's drivers beside it. The full source verdict travels with the response as a source object, the way a VS Code extension's declared repository does on V5.

Two further rows are notes. A source declared outside GitHub — skill-source-external:<host> — is listed as not assessed on this tier. A marketplace entry that names an npm package, an archive or a command instead of a repository — skill-no-source — is a shape, never a fault; S12 grades what that shape means at install. And on a ClawHub key S1 has no input at all: the Hub's API carries no source repository, so the check is listed as not checked without turning the clone dimension into not-assessed — the same rule a missing OpenSSF Scorecard result gets on a GitHub repository.

Measured on 20 September 2026 through the same code as /v1/skill/score, this row fired on 28 of the 189 skills.sh keys, 2 of the 310 official-marketplace plugins, 2 of the first 100 community plugins and 1 of the malicious set. The 28 are five repositories — 101-skills/superpowers, designed-by-ai/skills, flowkit-labs/skills, genmedia-labs/skills, prime-skills/runcomfy-agent-skills — under owners between 16 and 74 days old, whose own C1/C2 verdict is BLOCK and which carry 31 listings between them, each riding the repository's verdict; not 28 signals, five. The two official rows are nimble and pinecone, where the source repository's own C21 fired on an export NIMBLE_API_KEY=… line in a CLAUDE.md — the GitHub roster's known habit, not this roster's. The two community rows are agenticmail (a credential redirect in its AGENTS.md, a young owner, traction) and sentinal-stack (an owner 36 days old). The malicious row is Snyk's own fixture repository, snyk-labs/toxicskills-goof, the one BLOCK of the run — on S8 and S9, with S1 riding along. No skill on the three top lists was blocked by this check.

False positives we know about

A young owner with a real skill — the C1 case, inherited whole. Every developer's first repository sits on a new account, and the five skills.sh repositories above may be exactly that; on the day of the install the check cannot tell a first project from a lure. The finding shows the source's drivers by name, so what you are judging is the repository's age and its owner's, not the skill's text, and an override records the reason.

A source whose own roster fires on documentation. Two official plugins carry the row because their repository's CLAUDE.md sets an environment variable whose name ends in _API_KEY — the C21 regex's known cost, stated on that page. Inside the skill roster that same shape is graded by S15's own rule and is a note; the ride-along still carries the GitHub roster's reading of it, because that is what the source repository's verdict is.

What this check does not cover

The skill's own text. S1 says where the code came from and what the repository checks make of that; what the SKILL.md tells an agent to do is S9's question, what the scripts beside it do is S10's, and a repository that passes all 22 can still carry a SKILL.md that instructs the agent to read ~/.aws/credentials. A source this tier cannot read: an npm package, an archive, a command, a git URL off GitHub — each is a note that names the shape, and the deep scan is the tool for a package. ClawHub (@owner/slug) is parsed and routed but not assessed on this tier: its API names no repository, so S1 is a listed skip there, and a ClawHub key as a whole answers “not assessed” until the fetch ships — 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

For a skills.sh skill the source is in the URL: skills.sh lists owner/repo and the directory, and npx skills add owner/repo installs from that repository. For a Claude Code plugin, open the marketplace file and find the entry's source:

curl -s https://raw.githubusercontent.com/anthropics/claude-plugins-official/main/.claude-plugin/marketplace.json \
  | jq '.plugins[] | select(.name=="PLUGIN") | .source'

A relative path is the marketplace repository itself. A github object names the repository — and whether it carries a sha. Then look at that repository the way the C pages describe: the owner's created_at, the repository's, what sits in its releases. A repository created the same week as the account that owns it, publishing archives, is the shape every February campaign had.

Questions

Why does a skill inherit its repository's verdict? Because the skill is the repository. What npx skills add owner/repo installs is a directory out of that repository's tree, and what a Claude Code plugin installs is the repository its marketplace entry resolves to. The 22 checks already know how to read a repository's provenance and its execution surface, so they run on the resolved source on the same pass and the result is one row on the skill's report — critical when the source is on a confirmed campaign list, high when its own verdict is BLOCK, a note otherwise. In the 20 September 2026 measurement 28 of the 36 skills.sh REVIEWs were this row: five repositories under owners younger than 90 days, carrying 31 listings between them.

What does the check see on a ClawHub skill? Nothing, and it says so. ClawHub's public API answers a skill with its SKILL.md text and a moderation object, and carries no source repository, no file list and no checksum. S1 has no input there, so it is listed as not checked — a skip that does not turn the clone dimension into not-assessed, exactly as a missing OpenSSF Scorecard result is treated on a GitHub repository. Until the ClawHub fetch ships, a ClawHub key is parsed and routed but not assessed on this tier as a whole: every text check is a listed skip, the verdict is not assessed, and that is never a pass.

Does RepoGates hold the install of a skill? Only where a command line names it. In Claude Code with the RepoGates plugin, the hook sees npx skills add owner/repo and claude plugin install name@marketplace as Bash tool calls and refuses one that names a blocked repository before it runs, asks on a warning, and adds a note on a pass. It does not see git clone, package managers or curl outside that hook; /plugin install is a slash command the hook never sees; a skill copied by hand into ~/.claude/skills is never seen at all. The MCP tool check_skill answers an agent that asks, and the API answers anyone with a token.

Related checks

C1 Owner account age and C2 Repository age — the two checks that put the five skills.sh repositories' sources at BLOCK · S2 Listing and owner age — the same two ages, read for the skill's own listing · S12 Marketplace source pinning — whether the resolved source is pinned to a commit · C9 Release-asset binaries — the delivery path the February campaigns used, read on the source.

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; the incident record behind the malicious skills page (OpenSourceMalware, 1 February 2026; Snyk, 4 and 5 February 2026; John Stawinski IV, 18 June 2026); thresholds and weights from the product's policy and scoring tables.