Skip to content

ci: validate referenced component paths in plugin manifests - #244

Open
rootkiller6788 wants to merge 2 commits into
cursor:mainfrom
rootkiller6788:fix-validate-plugin-paths
Open

ci: validate referenced component paths in plugin manifests#244
rootkiller6788 wants to merge 2 commits into
cursor:mainfrom
rootkiller6788:fix-validate-plugin-paths

Conversation

@rootkiller6788

@rootkiller6788 rootkiller6788 commented Aug 21, 2026

Copy link
Copy Markdown

What

scripts/validate-plugins.mjs only checks plugin.json against the JSON schema and that the marketplace name matches the manifest name. A typo'd component path — e.g. "skills": "./skils/" or a renamed hooks/hooks.json — passes schema validation and CI but silently fails to load in Cursor. This PR adds an existence check for every path declared in plugin.json:

  • skills, agents, commands, rules, hooks, mcpServers, logo
  • Paths are resolved relative to the plugin directory (./ prefix stripped)
  • Inline hooks/mcpServers objects and absolute-URL logo values are skipped, matching the schema's allowed shapes
  • Glob patterns (e.g. skills/*) are validated against their static directory prefix so a typo in the base directory is still caught
  • Paths that escape the plugin directory (..) or are absolute are rejected

Also adds scripts/** to the validate-plugins.yml paths filter, so a PR that only changes the validator itself now triggers the job that runs it (previously a broken validator could merge without CI ever executing it).

Why

All 32 current marketplace plugins pass the new check (verified locally). The check only guards future PRs — which is the point of a merge gate: a contributor adding a new plugin or tweaking an existing manifest can't merge a path that Cursor will silently ignore.

Verification

  • node scripts/validate-plugins.mjs exits 0 on the current repo.
  • Intentionally breaking a path (skills -> ./skils/) produces a clear error and non-zero exit: ERROR: Plugin "teaching": skills path "./skils/" does not exist (resolved to teaching\skils).
  • Edge cases exercised: inline hooks object (skipped), absolute-URL logo (skipped), glob with valid/invalid prefix, and ../ path traversal (rejected).

Note

Low Risk
CI-only validation of plugin manifests; no runtime, auth, or data-handling changes.

Overview
Plugin CI now fails when a plugin.json points at component files that do not exist, instead of only schema-checking the manifest (typos like skils/ previously merged and then silently failed to load in Cursor).

After schema and name checks, the validator resolves skills, agents, commands, rules, hooks, mcpServers, and logo relative to the plugin directory. Inline objects and URL logos are skipped; globs are checked on their static prefix; empty, absolute, and .. paths are rejected.

The validate-plugins workflow also runs on scripts/** so validator-only PRs are actually exercised.

Reviewed by Cursor Bugbot for commit 0ac5375. Bugbot is set up for automated code reviews on this repo. Configure here.

validate-plugins.mjs only checks plugin.json against the JSON schema and
that the marketplace name matches. A typo'd component path (skills/agents/
commands/rules/hooks/mcpServers/logo) passes schema validation and CI but
silently fails to load in Cursor. Add an existence check for every path
declared in plugin.json, resolved relative to the plugin directory, with
inline hooks/mcpServers objects and absolute-URL logos skipped.

Also add scripts/** to the validate-plugins workflow paths filter so a PR
that only changes the validator itself triggers the job that runs it.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is ON, but it could not run because the branch was deleted or merged before autofix could start.

Reviewed by Cursor Bugbot for commit 7b25915. Configure here.

Comment thread scripts/validate-plugins.mjs Outdated
Comment thread scripts/validate-plugins.mjs Outdated
Addresses Bugbot review on cursor#244:
- Absolute URLs are only valid for `logo` per the schema; a URL in any
  other component field (skills/agents/commands/rules/hooks/mcpServers) was
  silently skipping the existence check and passing CI.
- An explicitly empty/whitespace component path now fails instead of being
  treated as 'not a path'.
@rootkiller6788

Copy link
Copy Markdown
Author

Thank you for the review. I've addressed both issues the Bugbot review flagged on commit 7b259150, and the fixes are in commit 0ac5375d on this branch.

1. Remote URLs in non-logo component fields silently bypassed the existence check. The original code returned early for anything isAbsoluteUrl matched, so a URL in skills/agents/commands/rules/hooks/mcpServers passed CI without ever checking the filesystem. Per schemas/plugin.schema.json, logo is the only field documented as accepting an absolute URL; every other component field is a local path. The validator now rejects URLs on non-logo fields while still accepting absolute-URL (and inline data:) logos:

if (isAbsoluteUrl(declared)) {
  if (field === "logo") return;
  fail(
    `Plugin "${pluginName}": ${field} path "${declared}" must be a local path relative to the plugin directory`
  );
  return;
}

2. Empty/whitespace component paths were silently treated as "not a path". The previous guard combined the non-string and empty checks into an early return, so an empty string slipped through. Empty and whitespace-only paths now fail explicitly:

if (declared.trim().length === 0) {
  fail(`Plugin "${pluginName}": ${field} path must not be empty`);
  return;
}

Verification. node scripts/validate-plugins.mjs exits 0 across every plugin currently listed in the marketplace. I also exercised the edge cases these checks are meant to catch — empty path, remote URL in commands, ../ traversal, absolute path, and a glob with an invalid static prefix (./nothere/*.md) — and each now produces the expected error with a non-zero exit.

CI note. The Bugbot check on the current head (0ac5375d) is green. The Validate plugins workflow is queued and waiting for maintainer approval to run on this fork PR — once approved it should pass, since the validator passes locally.

Could you please take another look?

@rootkiller6788
rootkiller6788 marked this pull request as ready for review August 22, 2026 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant