5 KiB
JetBrains Marketplace API notes
Reference notes for scanners/lib/vsix-fetch.mjs and scanners/lib/jetbrains-fetch-worker.mjs.
These endpoints are used to download JetBrains plugin archives for
/security ide-scan <url> (v6.6.0).
Base URL
https://plugins.jetbrains.com/
Metadata lookup
GET https://plugins.jetbrains.com/api/plugins/{numericId}
GET https://plugins.jetbrains.com/api/plugins/{numericId}/updates?size=N
{numericId}is an integer assigned by JetBrains when the plugin is first published. It is the first path segment (before the dash) in the user-facing URL — e.g.https://plugins.jetbrains.com/plugin/7973-intellivue→ numericId7973, slugintellivue.GET /api/plugins/{numericId}returns plugin metadata includingxmlId(the<id>fromplugin.xml),name,vendor.name,vendor.isVerified,programmingLanguage,urls. We use this only when--onlineis set, and never trustvendor.isVerifiedas a safety signal — it attests publisher identity, not plugin safety (see OX Security 2025).GET /api/plugins/{numericId}/updates?size=Nreturns the last N versions withid,version,cdate(unix millis),file(CDN path), andrecommended. We use this to resolve "latest stable" without trusting the plugin page HTML.
Direct download
Two equivalent URL shapes, both officially supported:
GET https://plugins.jetbrains.com/pluginManager?action=download&id={xmlId}&build={productCode}-{buildNumber}
GET https://plugins.jetbrains.com/plugin/download?pluginId={xmlId}&version={v}
action=downloadis what the IntelliJ IDE itself uses via its plugin manager.{productCode}isIC(IDEA Community),IU(IDEA Ultimate),PY,PS,GO,RD,CL,WS,RM,DB, etc.{buildNumber}is a short build string like241.18034.62. When both are present, the server returns the compatible version; otherwise it returns a 400.plugin/download?pluginId={xmlId}&version={v}is stable and simpler — we prefer this shape when the caller passes?version=. If no version is given we resolvelatestvia theupdatesendpoint first, then request that version explicitly.- The response is a ZIP (or in rare legacy cases a JAR).
Content-Typeisapplication/octet-streamorapplication/java-archive. The fetcher tolerates both.
Redirect host whitelist
The JetBrains CDN reroutes downloads. Our fetcher (vsix-fetch.mjs) accepts
redirects only to:
plugins.jetbrains.comdownloads.marketplace.jetbrains.comcache-redirector.jetbrains.com
Any other host aborts with Error: redirect not allowed: <host> and the worker
exits non-zero. This matches the VS Code Marketplace redirect policy in
marketplace-api-notes.md.
URL-to-numericId resolution
detectUrlType accepts three JetBrains URL shapes:
https://plugins.jetbrains.com/plugin/{numericId}-{slug}
https://plugins.jetbrains.com/plugin/{numericId}-{slug}/versions/{version}
https://plugins.jetbrains.com/pluginManager?action=download&id={xmlId}
https://plugins.jetbrains.com/plugin/download?pluginId={xmlId}
For the first two, we split the first path segment on - and take the
leading integer as numericId. For the action=download / download?pluginId
forms we pass the URL through directly.
Rate limits
JetBrains publishes no explicit rate limit. Observed in the field: low-tens of requests per minute per IP is safe. Our default is 1 req/s (conservative) — we issue at most three requests per URL scan (metadata + updates + download) so rate budget is generous.
Caps & defenses (shared with VS Code fetcher)
- TLS verification enabled (no
--insecureopt-in). - HTTPS only. Plain HTTP is rejected at
detectUrlTypeand at fetch time. - Manual redirect handling. Allowed hosts whitelisted per source type.
- 30-second total timeout via
AbortController. - 50MB compressed archive cap. Streaming reader aborts when cap exceeded.
- SHA-256 computed during streaming for
meta.source.sha256.
What is NOT supported (v6.6.0)
- No equivalent of OpenVSX — JetBrains Marketplace is the only distribution
channel, so URL scans fall through to direct-URL VSIX rules if the caller
passes a raw
.zipor.jarURL on any other host. - Custom plugin repositories (
updatePlugins.xmlfeeds on self-hosted servers) are out of scope. A target likehttps://my-repo.example.com/updatePlugins.xmlis not a plugin archive and will faildetectUrlType. - Archive signature verification — JetBrains ships plugins unsigned by default; the Marketplace signs metadata at publish time but the ZIP itself carries no embedded signature we can verify offline.
References
- JetBrains plugin-content — https://plugins.jetbrains.com/docs/intellij/plugin-content.html
- JetBrains plugin-configuration-file — https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html
- JetBrains Marketplace REST (informal) — https://plugins.jetbrains.com/docs/marketplace/api.html
- YouTrack IJPL-212393 — signature-warning inconsistency
- OX Security 2025 — JetBrains verified-badge bypass