Skip to main content

A visible remote image can still block canvas export

Updated 3 min readMarkdown

An image loads in a page. Drawing it onto a canvas also appears to work. Then the export throws a SecurityError. A visible picture does not establish that the application can read its pixels back.

Browsers place separate restrictions on reading a remote image through a canvas. When an image from another origin is drawn without the required CORS permission, the canvas becomes tainted. MDN explains the restrictions in its cross-origin image guide.

Check the request and the response

For a public image that does not need credentials, an application can request it in anonymous CORS mode:

const image = new Image();
image.crossOrigin = "anonymous";
image.src = imageUrl;
await image.decode();

Set crossOrigin before assigning src. The image server must also return an appropriate Access-Control-Allow-Origin header. Changing the JavaScript alone does not grant access to a server that has not permitted it.

If the server allows ordinary embedding but does not allow CORS access, this modified request can fail to load. Record that load failure: the application requested CORS access, and the server did not provide the response needed for it.

Keep the experiment small

Start with a new canvas and draw one image. Try the export immediately. Do not include a remote watermark, background texture, or another source yet. Otherwise, a permitted photograph can be blamed for a restriction introduced by a different image drawn later.

Compare that result with a same-origin test asset. If the same export function works for the local asset but fails after drawing the remote image, inspect the remote request in the browser's network panel. Record the final resource URL and response headers. A redirect can make the final origin different from the one suggested by the URL initially supplied to the application.

Do not try to repair the situation by changing a .png suffix to .jpg, lowering quality, or using a different canvas export method. Those changes do not supply the missing permission. A production error message should explain which source could not be exported, rather than reporting that the image format is unsupported.

Decide which sources the feature supports

If users supply their own files through a file picker, keep that workflow separate from the feature that imports arbitrary remote URLs. They have different failure cases. A conversion interface that mixes both paths behind one generic error makes troubleshooting unnecessarily difficult.

If the application controls the remote server, configure and test its CORS response for the intended callers. If it does not control that server, offer an authorized file-upload path or state that the particular URL cannot be exported. A server-side import feature needs an explicit design for access and resource limits. Keep that decision separate from the browser example.

For a bug report, a useful record includes the source origin, request mode, returned CORS header, and the operation that failed. The fact that the image was visible belongs in that report too, but visibility alone does not establish permission to export the canvas.

Keep this record with the failing example. The next person investigating the export can compare the request and response directly, without first having to reproduce every step of the larger editor interface.

3 views

About the author

  • I build Morphio, an online toolkit for working with image formats, including HEIC conversion. I share practical notes on image processing and web tools.

No comments yet. Be the first to comment.