badges/shields · error · InvalidParameter

domain is blocked

Error message

domain is blocked

What it means

The endpoint service maintains a blocked-domains list; after parsing the URL it rejects any hostname whose suffix matches an entry in that list, throwing InvalidParameter with prettyMessage 'domain is blocked'. This is a server-side SSRF/misuse mitigation for user-supplied endpoint URLs.

Source

Thrown at services/endpoint/endpoint.service.js:196

    const config = configModule.util.toObject()
    this._allowUnsecuredEndpointRequests =
      config?.public?.allowUnsecuredEndpointRequests || false
  }

  async handle(namedParams, { url }) {
    let protocol, hostname
    try {
      const parsedUrl = new URL(url)
      protocol = parsedUrl.protocol
      hostname = parsedUrl.hostname
    } catch (e) {
      throw new InvalidParameter({ prettyMessage: 'invalid url' })
    }
    if (protocol !== 'https:' && !this._allowUnsecuredEndpointRequests) {
      throw new InvalidParameter({ prettyMessage: 'please use https' })
    }
    if (blockedDomains.some(domain => hostname.endsWith(domain))) {
      throw new InvalidParameter({ prettyMessage: 'domain is blocked' })
    }

    const validated = await fetchEndpointData(this, {
      url,
      httpErrors,
      validationPrettyErrorMessage: 'invalid properties',
      includeKeys: true,
    })

    return this.constructor.render(validated)
  }
}

View on GitHub (pinned to 766fd8bc89)

Solutions

  1. Use a publicly reachable, allowlisted domain for the endpoint data
  2. If self-hosting, review and adjust the blocked-domains configuration only if the domain is legitimately safe
  3. Host the data on a different domain that is not blocked

Example fix

// before
/badge/endpoint?url=https://localhost:8080/data.json  // blocked
// after
/badge/endpoint?url=https://myapi.example.com/data.json
Defensive patterns

Strategy: validation

Validate before calling

const BLOCKED = ['localhost', '.local', '.internal']
function isAllowedHost(url) {
  try {
    const h = new URL(url).hostname
    return !BLOCKED.some(d => h.endsWith(d))
  } catch { return false }
}
// check the hostname against the instance blocklist before building the badge

Try / catch

try {
  const badge = await getEndpointBadge({ url })
} catch (e) {
  if (e.prettyMessage === 'domain is blocked') {
    console.error(`Domain not allowed for endpoint badge: ${new URL(url).hostname}`)
  } else throw e
}

Prevention

When it happens

Trigger: Calling /badge/endpoint with a url whose hostname ends with a blocked domain (e.g. localhost, .local, or any domain on the instance's blocklist).

Common situations: Trying to point the endpoint badge at internal hosts (localhost, 127.0.0.1, metadata services); the target domain was recently added to the blocklist; a subdomain of a blocked domain is used.

Related errors


AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30). Data as JSON: /api/errors/492b44708cb8773a. Report an issue: GitHub.