Safeguard
Security

browser-image-compression: Is Client-Side Image Compression Safe?

browser-image-compression shrinks images in the browser before upload. Here is how it works, its security trade-offs, and why client-side compression is never validation.

Marcus Chen
DevSecOps Engineer
6 min read

browser-image-compression is a JavaScript library that resizes and compresses JPEG, PNG, WebP, and BMP files entirely inside the user's browser before upload, and it is safe to use as long as you remember that anything happening on the client is a user-experience optimization, never a security control. That distinction is the whole point of this guide: browser image compression saves bandwidth and cost, but it cannot be trusted to sanitize or validate what reaches your server.

The library is genuinely useful. It runs on the Canvas API, offloads work to a Web Worker so the main thread stays responsive, and ships with TypeScript definitions. Compressing a 10 MB phone photo down to a few hundred kilobytes takes about a second on a mid-range laptop. But its value and its limits are two separate conversations.

What browser-image-compression does

The core use case is shrinking an image before it leaves the device. You give it a File and an options object, and you get back a smaller File or Blob.

import imageCompression from 'browser-image-compression';

async function handleUpload(imageFile) {
  const options = {
    maxSizeMB: 1,
    maxWidthOrHeight: 1920,
    useWebWorker: true,
  };
  const compressed = await imageCompression(imageFile, options);
  // upload `compressed`, not `imageFile`
  return compressed;
}

maxSizeMB caps the output size, maxWidthOrHeight bounds the resolution, and useWebWorker: true keeps the compression off the UI thread. Under the hood it draws the image to a canvas at the reduced dimensions and re-encodes it, which is why it works for raster formats and why it will not help with vector formats like SVG.

The payoff is concrete. A user on a mobile connection uploads a 500 KB image instead of 5 MB, so the upload feels instant. Your S3 egress, CDN storage, and database rows all shrink because images arrive pre-optimized. For profile photos, e-commerce listings, chat apps, and PWAs, that is a real win.

Why client-side compression is not a security boundary

Here is the trap. Because the library "processes" the file, it is tempting to think it also cleans it. It does not, and it cannot, for a structural reason: everything it does runs in code you shipped to a browser you do not control.

An attacker does not have to use your UI. They can call your upload endpoint directly with curl, skipping the JavaScript entirely. They can modify the library in their own browser, disable it, or replace the compressed output with an arbitrary payload. Any check that lives only on the client is advisory. The user, friendly or hostile, has the last word on what actually gets sent.

So browser-image-compression reducing a file to under 1 MB does not mean your server received an image under 1 MB. It does not mean the bytes are even an image. Treat the compressed result as an untrusted upload, identical to a raw one.

What the server still has to do

Everything that matters for security happens after the file arrives. At minimum:

  1. Verify the content type by inspecting bytes, not the extension or the declared MIME type. Read the magic number and confirm it matches an allowed image format.
  2. Enforce size limits server-side. Reject anything over your real cap before you load it into memory.
  3. Re-process the image on the server. Decoding and re-encoding with a trusted library strips most embedded payloads and normalizes the format. This also defends against polyglot files that are valid images and valid scripts at once.
  4. Store uploads outside the web root and serve them from a domain or path that cannot execute code, so a file that sneaks through cannot be requested as a script.
  5. Validate dimensions and pixel budget to blunt decompression-bomb style resource exhaustion.

If your stack exposes an upload API, a DAST scan against that endpoint is a good way to confirm the server-side controls actually fire, because it exercises the API the way an attacker would rather than the way your form does.

Vetting the library itself

The library is client-side JavaScript, so it becomes part of the code you serve to every visitor. That makes supply-chain hygiene relevant.

npm ls browser-image-compression
npm audit
npm pack browser-image-compression --dry-run

A few practical notes. Confirm the repository link on the npm page matches the source you intend to use, since ownership of popular front-end packages has changed hands. Pin the version rather than floating on a caret range, because a compromised or buggy release of a script that runs in every user's browser is a high-impact event. Continuous software composition analysis watches for advisories against your locked version after you ship, which a one-time npm audit at install time does not.

Getting the trade-offs right

Use browser-image-compression for what it is good at: cutting bandwidth, storage, and cost, and making uploads feel fast. Do not lean on it for anything security-relevant. Keep these principles in view:

  • Client-side compression is UX, server-side validation is security. They are not interchangeable.
  • Always re-encode images on the server; never serve raw uploaded bytes as-is.
  • Validate type, size, and dimensions on the server regardless of what the client did.
  • Pin and monitor the library like any other dependency that runs in your users' browsers.

FAQ

Is browser-image-compression safe to use?

Yes, for its intended purpose of shrinking images before upload to save bandwidth and cost. The important caveat is that it is a client-side optimization, not a security control. An attacker can bypass it entirely by calling your upload endpoint directly, so your server must independently validate every upload.

Does browser-image-compression sanitize or validate uploaded files?

No. It resizes and re-encodes raster images (JPEG, PNG, WebP, BMP) for size reduction, but it provides no security guarantee about the file that reaches your server. You still need server-side checks for content type, size, dimensions, and safe storage.

Can browser-image-compression replace server-side validation?

Never. Anything running in the browser is under the user's control and can be disabled or bypassed. Server-side validation, re-encoding, and safe storage are mandatory regardless of what happens on the client.

Which formats does browser-image-compression support?

It handles raster formats: JPEG, PNG, WebP, and BMP. It works by drawing the image to a canvas at reduced dimensions and re-encoding, so it does not apply to vector formats such as SVG.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.