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
- Move credentials out of the URL: pass them via an Authorization header (e.g. Basic base64(user:pass)) or the helper's headers option
- Use API keys/tokens in headers instead of URL userinfo
- If a legacy endpoint requires URL auth, proxy it through a service that injects credentials server-side
- 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
- Never embed basic-auth in URLs; always use headers
- Rotate any credentials that were pasted into URL fields
- Strip userinfo from URLs at config-ingestion time and store credentials separately
- Audit existing datasource/webhook configs for '@' in the authority component
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
- Only HTTP(S) URLs are allowed.
- Plugin URL must use HTTPS.
- Import url must not contain credentials
- REST query path must remain on the datasource origin
- Invalid object store key: path traversal is not allowed.
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/3fa20e2ae736cc19.
Report an issue: GitHub.