fabricjs/fabric.js · error · FabricError

Resource '${url}' is not allowed

Error message

Resource '${url}' is not allowed

What it means

Thrown by loadImage in objectEnlive when a configured resourceValidator rejects the URL being loaded. It is a security feature (SSRF/XSS protection): when a resourceValidator function is set in config, every image URL must be approved by it before loading. The message names the exact URL that was denied.

Source

Thrown at packages/core/src/util/misc/objectEnlive.ts:41

/**
 * Loads image element from given url and resolve it, or catch.
 * @param {String} url URL representing an image
 * @param {LoadImageOptions} [options] image loading options
 * @returns {Promise<HTMLImageElement>} the loaded image.
 */
export const loadImage = (
  url: string,
  { signal, crossOrigin = null, resourceValidator }: LoadImageOptions = {},
): Promise<HTMLImageElement> => {
  if (signal && signal.aborted) {
    return Promise.reject(new SignalAbortedError('loadImage'));
  }
  if (url && resourceValidator) {
    return Promise.resolve()
      .then(() => resourceValidator(url))
      .then((isAllowed) => {
        if (!isAllowed) {
          throw new FabricError(`Resource '${url}' is not allowed`);
        }
        if (signal && signal.aborted) {
          throw new SignalAbortedError('loadImage');
        }
        return loadImage(url, { signal, crossOrigin });
      });
  }
  return new Promise<HTMLImageElement>(function (resolve, reject) {
    if (signal && signal.aborted) {
      return reject(new SignalAbortedError('loadImage'));
    }
    const img = createImage();
    let abort: EventListenerOrEventListenerObject;
    if (signal) {
      abort = function (err: Event) {
        img.src = '';
        reject(err);
      };

View on GitHub (pinned to 2bd4992cab)

Solutions

  1. Inspect the URL in the message and update the resourceValidator to allow it if it is trusted (e.g. add the host to an allowlist)
  2. If the URL is untrusted, sanitize the stored JSON data to use safe/rewritten URLs instead of relaxing the validator
  3. Fix a validator that accidentally returns undefined/falsy for valid URLs (make sure it resolves boolean true)
  4. If intentional denial, catch the error and handle the missing image gracefully (placeholder)

Example fix

// before
import { config } from 'fabric';
config.resourceValidator = (url) => new URL(url, location.href).origin === location.origin;
// loading an external image throws: Resource 'https://cdn.example.com/a.png' is not allowed

// after
config.resourceValidator = (url) => {
  const u = new URL(url, location.href);
  return u.origin === location.origin || u.hostname === 'cdn.example.com';
};
Defensive patterns

Strategy: validation

Validate before calling

import { config } from 'fabric';
const isAllowed = config.resourceValidator
  ? await config.resourceValidator(url)
  : true;
if (!isAllowed) {
  // rewrite/skip the URL before loading
}

Type guard

const isSafeUrl = (url: string): boolean => {
  try {
    const u = new URL(url, location.href);
    return u.protocol === 'https:' && ALLOWED_HOSTS.has(u.hostname);
  } catch { return false; }
};

Try / catch

try {
  const img = await fabric.loadImage(url, { crossOrigin: 'anonymous' });
} catch (e) {
  if (e instanceof Error && e.message.startsWith("Resource '")) {
    // URL rejected by validator: use placeholder or rewrite URL
  } else throw e;
}

Prevention

When it happens

Trigger: Calling fabric.loadImage / enlivenObjects (fromJSON) with an image URL while config.resourceValidator is set and returns false (or a falsy value) for that URL, e.g. only allowing https:// or same-origin URLs but the object contains http:// or a data: URL.

Common situations: Apps that added a resourceValidator for security and then load older saved JSONs containing external http URLs, relative URLs, or data URIs; or a validator with a bug (returning undefined instead of true) causing every image to be rejected.

Related errors


AI-assisted analysis of fabricjs/fabric.js@2bd4992cab (2026-08-28). Data as JSON: /api/errors/ec1c12e664572f3e. Report an issue: GitHub.