Safeguard
Open Source

FileSaver.js (file-saver): Package Review and Download Security

The file saver npm package still powers client-side downloads in millions of builds, but it has not shipped a release since 2020. Here is what that means for your dependency tree.

Priya Mehta
DevSecOps Engineer
7 min read

The file saver npm package (file-saver, better known as FileSaver.js) is a small, MIT-licensed utility for triggering client-side file downloads, and while it has no known vulnerabilities, its last release — 2.0.5 — shipped in late 2020, so you should treat it as a stable but dormant dependency. That combination is common in the npm ecosystem and it deserves a more nuanced answer than "unmaintained, remove it." This review covers what the package actually does, where the real security considerations live (hint: mostly in what you feed it, not the library itself), and when the browser's native APIs make it unnecessary.

What file-saver actually does

FileSaver.js, written by Eli Grey, exposes a single function:

import { saveAs } from 'file-saver';

const blob = new Blob([csvString], { type: 'text/csv;charset=utf-8' });
saveAs(blob, 'export.csv');

Under the hood it creates an object URL for the Blob, builds an anchor element with a download attribute, synthesizes a click, and revokes the URL afterwards. It also carries fallback paths for older browsers and quirks handling for Safari, which historically ignored the download attribute in various scenarios. That compatibility shim is the entire reason the library exists — the core trick is about ten lines of vanilla JavaScript.

The package sees on the order of 6–7 million weekly downloads on npm, which tells you two things: it solved a real problem, and an enormous amount of production code depends on a module that is no longer evolving.

Maintenance status: dormant, not dangerous

Version 2.0.5 is the latest release, published in November 2020. The GitHub repository (eligrey/FileSaver.js) accumulates issues and pull requests with little activity. Snyk and other advisory databases list no known vulnerabilities against any published version at the time of writing.

For a dependency risk assessment, that puts file-saver in the "frozen utility" bucket rather than the "abandoned attack surface" bucket:

  • It has zero runtime dependencies, so it cannot pull in a compromised transitive package.
  • Its API surface is one function that touches DOM APIs, not network or storage.
  • The code is small enough to audit in one sitting.

The realistic risks are indirect. A dormant package with millions of downloads is an attractive hijack target: if the npm account or the repository were compromised, a malicious 2.0.6 would propagate fast precisely because so many lockfiles pin ^2.0.5. This is the same pattern that made incidents like the ua-parser-js hijack painful. Pinning exact versions and reviewing lockfile diffs on update is the practical mitigation; an SCA tool such as Safeguard's SCA product can also alert you when a long-dormant package suddenly publishes a new version, which is itself a signal worth investigating.

The security work is in the content, not the library

Most "download security" questions attributed to file-saver are really about what you put in the Blob. The library will faithfully save whatever bytes you hand it. Three areas deserve attention.

Filename handling

If the filename comes from user input or an API response, sanitize it. Browsers strip path separators from the download attribute, so classic path traversal into arbitrary directories does not work from a web page, but misleading names still do. A file named invoice.pdf.html opens in a browser when double-clicked; report.csv with embedded formulas becomes a CSV injection vector when opened in Excel.

function safeFilename(name) {
  return name.replace(/[^a-zA-Z0-9._-]/g, '_').slice(0, 120);
}

CSV and spreadsheet injection

If your app exports user-generated data to CSV, prefix cells that begin with =, +, -, or @ with a single quote or a tab character before building the blob. Excel and LibreOffice will otherwise evaluate them as formulas, and payloads using =HYPERLINK or DDE-style functions have been used for real data exfiltration.

MIME types

Set an accurate type on the Blob. Saving HTML content with type: 'text/plain' does not make it safe — the file extension governs what happens on the user's machine — but a correct MIME type avoids browser-side sniffing surprises and keeps behavior predictable across platforms.

None of this is a flaw in file-saver. It is the standard trust boundary problem of any export feature, and it applies equally if you replace the library with native APIs.

Native alternatives in 2025

Modern browsers have narrowed the gap that FileSaver.js was built to bridge. Two options cover most use cases.

The anchor download pattern works everywhere that matters today, including current Safari:

function saveBlob(blob, filename) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

The File System Access API (showSaveFilePicker) gives users a real save dialog and supports streaming large files without buffering everything in memory. As of 2025 it ships in Chromium-based browsers but not in Firefox or Safari, so it needs the anchor pattern as a fallback:

if ('showSaveFilePicker' in window) {
  const handle = await window.showSaveFilePicker({
    suggestedName: 'export.csv',
    types: [{ description: 'CSV', accept: { 'text/csv': ['.csv'] } }],
  });
  const writable = await handle.createWritable();
  await writable.write(blob);
  await writable.close();
} else {
  saveBlob(blob, 'export.csv');
}

If your browser support matrix starts at evergreen browsers, ten lines of your own code eliminate the dependency entirely. If you still support legacy Safari or embedded WebViews with odd behavior, keeping the npm file saver package is a defensible choice — it encodes years of quirk knowledge you do not want to rediscover.

Wrappers and lookalikes

The ecosystem around file-saver has a few traps worth knowing:

  • filesaver.js (lowercase, no hyphen) and other near-name packages exist on npm. Some are legitimate historical mirrors; some are stale forks. Always install file-saver exactly, and watch for typosquats like file-savers or filesaver in code review.
  • Framework wrappers such as ngx-filesaver for Angular add convenience but another maintainer to trust. Check that the wrapper pins a sane version of the core library.
  • @types/file-saver provides TypeScript definitions and is maintained separately through DefinitelyTyped; version drift between the types and the library is harmless here because the API has not changed.

Typosquatting checks are tedious to do by hand across a large monorepo, which is where automated dependency review in CI earns its keep. If you want a structured way to evaluate packages like this one, the Safeguard Academy has hands-on material on scoring dependency health beyond "does it have CVEs."

Keep it or drop it: a decision rubric

  • Keep if you support older browsers or WebViews, the package is already in your tree, and you pin exact versions with lockfile review. Dormant plus zero-deps plus no CVEs is an acceptable risk profile.
  • Replace with native code if you target evergreen browsers only. Fewer dependencies means fewer hijack targets and one less entry in every SBOM and audit.
  • Never vendor-fork casually. If you do fork to patch a quirk, you now own the maintenance burden the original author set down.

Whatever you choose, make it a recorded decision. "We know this package is dormant and accept it because X" is a fine line in a dependency review doc; silent inheritance is how frozen utilities become forgotten liabilities.

FAQ

Is the file-saver npm package safe to use in 2025?

Yes, with caveats. Version 2.0.5 has no known vulnerabilities and no runtime dependencies. The main risk is ecosystem-level: a dormant, hugely popular package is a hijack target, so pin exact versions and review lockfile changes.

Is FileSaver.js still maintained?

Effectively no. The last npm release was 2.0.5 in November 2020, and repository activity is minimal. Treat it as feature-complete and frozen rather than actively supported.

What is the native alternative to file-saver?

For evergreen browsers, create an object URL and click an anchor with a download attribute. On Chromium browsers, the File System Access API (showSaveFilePicker) additionally offers real save dialogs and streaming writes.

Does file-saver have any known CVEs?

No CVEs are recorded against file-saver in the major advisory databases at the time of writing. Security issues around downloads almost always live in the content you generate — filenames, CSV formulas, MIME types — not in the library.

Never miss an update

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