fix(registry): reject bare package-name sources for kind=skill (#6444)

Control #1 (#6442) accepts any package-name-shaped source, which is right
for kind=mcp (npx -y <pkg>) but wrong for kind=skill: install_source only
reaches the npx-package branch for kind auto/mcp, so a bare name like "123"
published as a skill resolves to an MCP server, not a skill — it slipped
through the syntactic gate. Guard it in PublishSchema so a skill source must
be a SKILL.md URL or a GitHub repo path.
This commit is contained in:
YHH authored and GitHub committed 2026-07-14 10:49:22 +08:00
1 parent 75e75cad7e
commit b07c0e9956
2 files changed
+18

No files matched your search

@@ -40,4 +40,11 @@ describe("PublishSchema source", () => {
it("allows a whole-repo GitHub source for kind=mcp (a repo root is a valid plugin/MCP source)", () => {
expect(parse({ kind: "mcp", source: "https://github.com/o/r" }).success).toBe(true);
});
it("rejects a bare package name for kind=skill (it would resolve as an MCP, not a skill)", () => {
for (const source of ["123", "my-skill", "@scope/pkg"]) {
expect(parse({ kind: "skill", source }).success, source).toBe(false);
expect(parse({ kind: "mcp", source }).success, source).toBe(true);
}
});
});
@@ -107,6 +107,17 @@ export const PublishSchema = z
"source points at a whole GitHub repo, which installs every skill in it. Point it at one skill — e.g. https://github.com/<owner>/<repo>/tree/<branch>/skills/<name> or a raw SKILL.md URL.",
});
}
// A skill lives in a SKILL.md file/dir; install_source only reaches the
// npx-package branch for kind auto/mcp, so a bare package-name source
// (e.g. "123") resolves as an MCP server, never a skill.
if (val.kind === "skill" && looksLikePackage(val.source)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["source"],
message:
"a skill source must be a SKILL.md URL or a GitHub repo path, not a bare package name.",
});
}
});
export type PublishInput = z.infer<typeof PublishSchema>;