fix(marketplace): restore gaia entry lost to duplicate JSON keys#119
Merged
Conversation
The gaia-data-downloader entry in .claude-plugin/marketplace.json was merged into the zarr-chunk-optimization object, so that one object held duplicate "name"/"source"/"description" keys. JSON last-wins parsing collapsed the two into a single entry (zarr), silently dropping gaia-data-downloader from the catalog; the merge also overwrote zarr-chunk-optimization's keywords with gaia's. Impacts: - `copilot plugin install gaia-data-downloader@rse-plugins` failed with "not found in marketplace", breaking .devcontainer/post-create.sh (#105). - Security: every scan in validate-plugins.yml built its target list from `jq -r '.plugins[].source'` of the catalog, so gaia's files were excluded from the secret, dangerous-pattern, suspicious-URL, and MCP dependency scans. A secret or malicious pattern under community-plugins/ gaia-data-downloader/ would have passed CI unscanned. Fixes: - Split the merged object into well-formed gaia-data-downloader and zarr-chunk-optimization entries, restoring each plugin's own keywords. - Add a duplicate-JSON-key CI guard (check_duplicate_json_keys.py); the existing `jq empty` check accepts duplicate keys. - Enumerate plugin directories from the filesystem (plugins/*, community-plugins/*) in the four security scans instead of the catalog, so unlisted/mis-cataloged plugins are still scanned. This newly covers containerization, supply-chain-security, and uiux-design-team, which the catalog-driven scans had been skipping entirely. - Add community-plugins/** and .github/scripts/** to the pull_request paths filter so community-only changes trigger these checks.
Enumerating plugins/* and community-plugins/* from the filesystem pulled the unlisted supply-chain-security plugin into scan scope, whose incident-response runbooks legitimately document attack patterns (e.g. `base64 -d`, `eval(...)`), tripping the dangerous-pattern scan and failing CI. Revert the four security scans to the catalog-based target list. The new duplicate-key guard already prevents a plugin from silently dropping out of the catalog (and thus out of scan scope), which was the actual reported defect, so gaia is scanned again now that it is a valid catalog entry. Extending scan coverage to unlisted plugins is worthwhile but requires the heuristics to tell security documentation apart from dangerous code; left as a follow-up rather than weakening the checks here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
.claude-plugin/marketplace.jsonhad a single object with duplicate keys:gaia-data-downloader'sname/source/descriptionwere merged into thezarr-chunk-optimizationobject. JSON last-wins parsing collapsed the two into one entry, sogaia-data-downloadersilently vanished from the catalog and zarr's keywords were overwritten with gaia's.copilot plugin install gaia-data-downloader@rse-plugins(used in.devcontainer/post-create.sh) — see bug: plugin@marketplace not working forgaia_data_downloader#105 — and, because every CI security scan builds its target list fromjq -r '.plugins[].source', it also dropped gaia's files out of scan scope while it was missing from the catalog.jq emptyaccepts duplicate keys, so this defect class passed validation). With the entry restored and the guard in place, gaia stays in the catalog and therefore in scan scope.Changes
Catalog (
.claude-plugin/marketplace.json)jq -r '.plugins[].name'now lists 9 plugins including bothgaia-data-downloaderandzarr-chunk-optimization.plugin.jsonmanifests.CI (
.github/workflows/validate-plugins.yml).github/scripts/check_duplicate_json_keys.py, which uses Python'sobject_pairs_hookto reject duplicate keys (jq emptycannot detect them).community-plugins/**and.github/scripts/**to thepull_requestpaths:filter so community-plugin and CI-script changes trigger the workflow (previously community-only PRs skipped it entirely).New file
.github/scripts/check_duplicate_json_keys.py— walks all*.json(skippingtsconfig*,.git,node_modules) and fails on any duplicate key, emitting a GitHub Actions error annotation.Test plan
jq -r '.plugins[].name'lists 9 plugins incl.gaia-data-downloaderandzarr-chunk-optimizationjq -r '.plugins[].source'includes./community-plugins/gaia-data-downloader; zarr keywords restored to its own (not gaia's)\ssemantics)plugin.json+README.md)Validate Pluginsworkflow green on this PRNotes / follow-up
plugins/*+community-plugins/*from the filesystem (so unlisted plugins are scanned too), but that pulls the unlistedsupply-chain-securityplugin into scope, whose incident-response runbooks legitimately document attack patterns (base64 -d,eval(...)) and trip the dangerous-pattern heuristics. Since this repo's plugins are largely Markdown, cleanly separating security documentation from dangerous code is a separate design change and is left as a follow-up. The duplicate-key guard already closes the reported gap (a plugin can no longer silently drop out of the catalog).Closes #105
🤖 Generated with Claude Code