Budibase/budibase · error · Error

The plugin origin must be from NPM

Error message

The plugin origin must be from NPM

What it means

parseNpmUrl requires the https: protocol for npm plugin sources. Non-https URLs (http, git+ssh, registry:) are rejected even if otherwise well-formed; the actual npm host whitelist is enforced separately in npmUpload.

Source

Thrown at packages/server/src/api/controllers/plugin/npm.ts:18

import { utils as coreUtils } from "@budibase/backend-core"
import {
  deleteFolderFileSystem,
  getPluginMetadata,
} from "../../../utilities/fileSystem"
import { join } from "path"
import { downloadUnzipTarball } from "./utils"

function parseNpmUrl(url: string): URL {
  let parsed: URL
  try {
    parsed = new URL(url)
  } catch {
    throw new Error("Invalid NPM URL")
  }

  if (parsed.protocol !== "https:") {
    throw new Error("The plugin origin must be from NPM")
  }

  return parsed
}

function isAllowedNpmHost(host: string): boolean {
  return host === "www.npmjs.com" || host === "registry.npmjs.org"
}

export async function npmUpload(url: string, name: string, headers = {}) {
  let npmTarballUrl = url
  let pluginName = name

  const parsedInput = parseNpmUrl(npmTarballUrl)
  if (!isAllowedNpmHost(parsedInput.hostname)) {
    throw new Error("The plugin origin must be from NPM")
  }

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Switch the URL to https:// (e.g. https://registry.npmjs.org/<pkg>/-/<pkg>-<version>.tgz)
  2. Download/publish the tarball on the public npm registry and use its https URL
  3. If behind an http-only mirror, mirror the package to a https host

Example fix

// before
const url = 'http://registry.npmjs.org/my-plugin/-/my-plugin-1.0.0.tgz'
// after
const url = 'https://registry.npmjs.org/my-plugin/-/my-plugin-1.0.0.tgz'
Defensive patterns

Strategy: validation

Validate before calling

const u = new URL(url)
if (u.protocol !== 'https:') throw new Error('NPM plugin URL must use https://')

Type guard

function isHttpsUrl(url: string): boolean {
  try { return new URL(url).protocol === 'https:' } catch { return false }
}

Try / catch

try {
  await installPlugin({ source: 'NPM', url })
} catch (err) {
  if (err.message === 'The plugin origin must be from NPM') {
    console.error('Rewrite the URL with https:// scheme')
  }
}

Prevention

When it happens

Trigger: npmUpload called with an http:// npm URL, a git+ssh:// or git+https:// URL, or any URL whose protocol is not exactly https:.

Common situations: Copying an http link from an internal mirror; using a tarball link from a private registry served over http; git+ssh URLs from package.json dependency entries.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/3d02ee05c73dd750. Report an issue: GitHub.