payloadcms/payload · error · APIError

The provided URL is not allowed.

Error message

The provided URL is not allowed.

What it means

APIError (HTTP 400, 'The provided URL is not allowed.') thrown when an allowList is configured for pasteURL and the initial requested URL does not match any allowList entry. isURLAllowed compares protocol (with appended ':'), hostname/port/search for equality, and pathname via glob (*/**) translation; an invalid URL denies by default.

Source

Thrown at packages/payload/src/uploads/endpoints/getFileFromURL.ts:66

  const { searchParams } = new URL(req.url)
  const src = searchParams.get('src')

  if (!src || typeof src !== 'string') {
    throw new APIError('A valid URL string is required.', 400)
  }

  const hasAllowList =
    typeof config.upload.pasteURL === 'object' && Array.isArray(config.upload.pasteURL.allowList)

  let fileURL: string
  try {
    fileURL = new URL(src).href
  } catch {
    throw new APIError('A valid URL string is required.', 400)
  }

  if (hasAllowList && !isURLAllowed(fileURL, config.upload.pasteURL.allowList)) {
    throw new APIError('The provided URL is not allowed.', 400)
  }

  let redirectCount = 0
  const maxRedirects = 3
  let response!: Response

  while (true) {
    if (hasAllowList && isURLAllowed(fileURL, config.upload.pasteURL.allowList)) {
      // Allow-listed URLs bypass SSRF filtering (e.g. internal/localhost CDNs)
      response = await fetch(fileURL, {
        headers: { 'Accept-Encoding': 'identity' },
        redirect: 'manual',
        signal: AbortSignal.timeout(30_000),
      })
    } else {
      response = await safeFetch(fileURL, {
        headers: {
          'Accept-Encoding': 'identity',

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Add the source host (and protocol, pathname pattern) to upload.pasteURL.allowList.
  2. Widen the pathname glob — use '**' for multi-segment matching (e.g. '/media/**').
  3. Confirm the protocol field matches (pasteURL compares 'https' → 'https:').
  4. On the client, restrict the picker to allow-listed hosts so users can't submit disallowed URLs.

Example fix

// before — too narrow
pasteURL: { allowList: [{ hostname: 'cdn.example.com', pathname: '/img/*' }] }
// after — cover the host and broad path
pasteURL: {
  allowList: [
    { hostname: 'cdn.example.com', protocol: 'https', pathname: '/**' },
    { hostname: 'images.example.com', protocol: 'https', pathname: '/**' },
  ],
}
Defensive patterns

Strategy: validation

Validate before calling

import { isURLAllowed } from 'payload/utilities' // if exported; else replicate
const ALLOW_LIST = [{ hostname: 'cdn.example.com', protocol: 'https', pathname: '/**' }]
function urlAllowed(u: string): boolean {
  return isURLAllowed ? isURLAllowed(u, ALLOW_LIST) : (() => { try { const p = new URL(u); return ALLOW_LIST.some(a => p.hostname === a.hostname && p.protocol === a.protocol + ':') } catch { return false } })()
}
if (!urlAllowed(src)) throw new Error('That host is not in the paste-URL allow list')

Type guard

const matchesAllowList = (u: string, list: Array<{ hostname: string; protocol?: string }>): boolean => {
  try {
    const p = new URL(u)
    return list.some((a) => p.hostname === a.hostname && (!a.protocol || p.protocol === `${a.protocol}:`))
  } catch { return false }
}

Try / catch

try {
  await fetch(`/api/media/paste-url?src=${encodeURIComponent(src)}`, { method: 'POST' })
} catch (e) {
  if (/not allowed/.test(e.message)) alert('Use a URL from an allowed host')
}

Prevention

When it happens

Trigger: pasteURL.allowList is set (array of {hostname, protocol, pathname?, port?} criteria) and the user-submitted src URL's hostname, protocol, port, or pathname fails to match any entry. Also fires if the URL fails to parse (isURLAllowed returns false on parse error).

Common situations: Allow-listing cdn.example.com but the user pastes from a different host; protocol mismatch (allowList https, user submits http); pathname glob too narrow (e.g. '/images/*' won't match '/videos/x.mp4'); forgetting to allow the protocol key; typo in the allowList hostname.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/9ae2e5d5be3a782c. Report an issue: GitHub.