Budibase/budibase · error

URL must not include credentials.

Error message

URL must not include credentials.

What it means

parseUrl() rejects URLs containing embedded userinfo (parsed.username or parsed.password, e.g. https://user:pass@host). These credentials would leak into logs, redirect targets and error messages, so the SSRF-safe fetch helper forbids them outright with Error('URL must not include credentials.').

Source

Thrown at packages/backend-core/src/utils/outboundFetch.ts:29

  "cookie",
  "cookie2",
  "proxy-authorization",
]

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

  if (!ALLOWED_PROTOCOLS.has(parsed.protocol)) {
    throw new Error("Only HTTP(S) URLs are allowed.")
  }

  if (parsed.username || parsed.password) {
    throw new Error("URL must not include credentials.")
  }

  return parsed
}

function isRedirect(status: number): boolean {
  return [301, 302, 303, 307, 308].includes(status)
}

async function resolveSafePinnedIp(url: string): Promise<string> {
  const parsed = parseUrl(url)
  const addresses = await resolveAddress(parsed.hostname)
  if (addresses.length === 0) {
    throw new Error("URL is blocked or could not be resolved safely.")
  }

  for (const address of addresses) {
    if (await isBlacklisted(address)) {

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Move credentials out of the URL: pass them via an Authorization header (e.g. Basic base64(user:pass)) or the helper's headers option
  2. Use API keys/tokens in headers instead of URL userinfo
  3. If a legacy endpoint requires URL auth, proxy it through a service that injects credentials server-side
  4. Rotate any credentials that were embedded in URLs - they may have been logged

Example fix

// before
await outboundFetch("https://user:pass@api.example.com/v1/data")
// after
const auth = Buffer.from("user:pass").toString("base64")
await outboundFetch("https://api.example.com/v1/data", {
  headers: { Authorization: `Basic ${auth}` },
})
Defensive patterns

Strategy: validation

Validate before calling

// detect userinfo in a URL before fetching
function urlHasCredentials(u: string): boolean {
  try {
    const parsed = new URL(u)
    return Boolean(parsed.username || parsed.password)
  } catch {
    return true
  }
}
if (urlHasCredentials(url)) throw new Error("Move credentials to headers")

Type guard

function isCredentialFreeUrl(u: string): boolean {
  try {
    const p = new URL(u)
    return !p.username && !p.password
  } catch {
    return false
  }
}

Try / catch

try {
  const res = await outboundFetch(url)
} catch (e: any) {
  if (e?.message === "URL must not include credentials.") {
    // extract creds, strip from URL, send as Authorization header instead
  } else throw e
}

Prevention

When it happens

Trigger: outboundFetch called with "https://user:pass@api.example.com/..."; also basic-auth URLs copied from other tools; a datasource/webhook config where someone embedded auth in the URL.

Common situations: Migrating configs from curl commands that used -u user:pass with the URL form; legacy APIs documented with credentials-in-URL; secrets accidentally pasted into URL fields in the builder.

Related errors


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