Budibase/budibase · error · HTTPError

Only HTTP(S) URLs are allowed for query import

Error message

Only HTTP(S) URLs are allowed for query import

What it means

parseImportUrl throws this HTTPError(400) when the URL parses but its protocol is not in ALLOWED_IMPORT_PROTOCOLS (HTTP/HTTPS), blocking schemes like file:, ftp:, data:.

Source

Thrown at packages/server/src/api/controllers/query/import/index.ts:83

  }
}

const stringToHashKey = (input: string) =>
  crypto.createHash("sha512").update(JSON.stringify(input)).digest("hex")

const buildCacheKey = (input: ImporterInput) =>
  `openapiSpecs:${stringToHashKey(JSON.stringify("data" in input ? input.data : input.url))}`

function parseImportUrl(url: string): URL {
  let parsed: URL
  try {
    parsed = new URL(url)
  } catch {
    throw new HTTPError("Invalid import url", 400)
  }

  if (!ALLOWED_IMPORT_PROTOCOLS.has(parsed.protocol)) {
    throw new HTTPError("Only HTTP(S) URLs are allowed for query import", 400)
  }

  if (parsed.username || parsed.password) {
    throw new HTTPError("Import url must not contain credentials", 400)
  }

  return parsed
}

async function fetchFromUrl(url: string): Promise<string> {
  try {
    // validate protocol / credentials up front for clear 400 errors
    parseImportUrl(url)
    // fetchWithBlacklist resolves and validates the target, pins the request to
    // the validated IP (preventing DNS rebinding between validation and the
    // actual connection) and safely follows redirects, re-validating each hop.
    const response = await utils.fetchWithBlacklist(url)

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Use an http:// or https:// URL for the import source
  2. Upload local files directly instead of referencing file:// paths
  3. Move FTP-hosted data behind an HTTP(S) endpoint

Example fix

// before
const url = 'file:///home/user/data.json'
// after
const url = 'https://myapi.example.com/data.json'
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = new Set(['http:', 'https:'])
const u = new URL(url)
if (!ALLOWED.has(u.protocol)) throw new Error('Only http:// or https:// import sources are supported')

Type guard

function isHttpUrl(url: string): boolean {
  try { return ['http:', 'https:'].includes(new URL(url).protocol) } catch { return false }
}

Try / catch

try {
  await importSource(url)
} catch (err) {
  if (err instanceof HTTPError && err.message.includes('Only HTTP(S) URLs')) {
    // reject file://, ftp://, data: sources and ask for an HTTP(S) endpoint
  }
}

Prevention

When it happens

Trigger: Importing a query source from a URL using ftp://, file://, data:, or other non-HTTP(S) schemes.

Common situations: Trying to import local files via file:// URLs; FTP-hosted datasets; data: URIs pasted as source URLs.

Related errors


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