Skip to content

fix(claude): preserve marketplace source shape for allowlist matching#345

Open
abezzub-dr wants to merge 2 commits into
majorcontext:mainfrom
abezzub-dr:fix/claude-marketplace-source-shape
Open

fix(claude): preserve marketplace source shape for allowlist matching#345
abezzub-dr wants to merge 2 commits into
majorcontext:mainfrom
abezzub-dr:fix/claude-marketplace-source-shape

Conversation

@abezzub-dr
Copy link
Copy Markdown
Contributor

@abezzub-dr abezzub-dr commented Apr 28, 2026

Summary

  • Stop normalizing {source: github, repo: X} marketplace entries to {source: git, url: https://github.com/X.git} in LoadSettings, LoadKnownMarketplaces, and ConfigToSettings. Pass the original source shape through to the container.
  • Update the marketplace extraction loop in internal/run/manager.go to handle both {Source: github, Repo} and {Source: git, URL} entries when populating MarketplaceConfig.
  • Update tests that locked in the old normalized output.

Why

When a host's ~/.claude/remote-settings.json declares strictKnownMarketplaces — an exact-match allowlist of {source, repo|url} pairs that moat copies into the container (#306) — the normalized form no longer matched the shape the host was registered with. Claude Code inside the container rejected every plugin install with Marketplace "X" is not in the allowed marketplace list, even though plain claude on the host worked because its known_marketplaces.json registration matched the allowlist's github+repo entry.

Concretely, the bug path:

  1. LoadSettings rewrote {source: github, repo: company-name/claude-marketplace}{source: git, url: https://github.com/digitalroute/dr-claude-marketplace.git}.
  2. manager.go then stripped the URL back to company-name/claude-marketplace for MarketplaceConfig.Repo, but kept Source: "git".
  3. GenerateKnownMarketplaces saw Source == "git" and wrote {source: git, url: "company-name/claude-marketplace"} into the container's known_marketplaces.json — a path stuffed into a URL field, matching neither allowlist entry.

Preserving the original shape end-to-end avoids the lossy conversion entirely. Downstream consumers (GenerateKnownMarketplaces, CloneMarketplace, claude plugin marketplace add) already accept either form, so no further changes were needed.

Test plan

  • go test -race ./... — full suite green
  • go vet ./internal/providers/claude/... ./internal/run/... — clean
  • gofmt -l — clean on changed files
  • Manual test: run moat claude in a project whose host ~/.claude/remote-settings.json contains strictKnownMarketplaces and confirm plugins install without "not in the allowed marketplace list" errors
  • Manual test: confirm moat claude still works for users without strictKnownMarketplaces (no regression for the unconstrained path)

Marketplace entries like {source: github, repo: owner/repo} were being
rewritten to {source: git, url: https://github.com/owner/repo.git} in
LoadSettings, LoadKnownMarketplaces, and ConfigToSettings before being
written into the container's settings.json and known_marketplaces.json.

When a host ~/.claude/remote-settings.json declares strictKnownMarketplaces
(an exact-match allowlist of {source, repo|url} pairs that moat copies
into the container), the normalized form no longer matched the shape the
host had registered with, so Claude Code inside the container rejected
every plugin install with "Marketplace ... is not in the allowed
marketplace list" — even though plain `claude` on the host worked.

Stop normalizing at those three sites and pass the original source shape
through. Update the manager.go extraction loop to switch on
entry.Source.Source and copy either Repo (github) or URL (git) into
MarketplaceConfig.Repo. Downstream consumers (GenerateKnownMarketplaces,
CloneMarketplace, `claude plugin marketplace add`) already accept either
form, so no changes are needed there.

Update existing tests that locked in the old normalized output to assert
the preserved shape.
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