The npm xlsx package is safe to use, but only if you understand an unusual wrinkle: the SheetJS project stopped publishing new releases to the npm registry, so the fixes for its two notable vulnerabilities are not available through a normal npm install xlsx. This is one of the few widely used libraries where "just upgrade" does not work the way you expect, and getting it wrong leaves a known prototype-pollution flaw in your build. Here is what the xlsx npm package does, what its real vulnerabilities are, and how to install a patched version.
What the xlsx npm package does
SheetJS Community Edition, published as xlsx, reads and writes spreadsheet files: XLSX, XLS, CSV, and many more formats. It is the default choice when a Node.js or browser app needs to parse an uploaded spreadsheet or generate one for download.
const XLSX = require('xlsx');
const workbook = XLSX.readFile('upload.xlsx');
const rows = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
The security-relevant part is readFile and read. Parsing a spreadsheet means parsing a complex, attacker-controllable binary or XML format, and that is where the vulnerabilities live. If your app only ever writes spreadsheets and never reads untrusted ones, your exposure is much lower.
The two CVEs you need to know
CVE-2023-30533, prototype pollution. All versions of SheetJS Community Edition through 0.19.2 are vulnerable to prototype pollution when reading a specially crafted file. An attacker who can get your app to parse a malicious spreadsheet can pollute JavaScript object prototypes, which can lead to denial of service, data tampering, or in the wrong conditions code execution. It was resolved in 0.19.3.
CVE-2024-22363, regular expression denial of service. All versions through 0.20.1 are vulnerable to a ReDoS, where a crafted input drives a regular expression into catastrophic backtracking and stalls the process. It was resolved in 0.20.2.
Both share the same precondition: they bite when your application reads untrusted spreadsheet content. Neither affects a pure export workflow.
The catch: npm is not where the fixes are
Here is the part that trips people up. The last version SheetJS published to the public npm registry is 0.18.5, which predates both fixes. Running npm i xlsx from the default registry gives you a version that is vulnerable to CVE-2023-30533 and CVE-2024-22363. There is no npm install xlsx@latest that resolves the problem, because the patched releases (0.19.3, 0.20.2, and newer) were never pushed there.
The project distributes current versions from its own CDN instead. The maintainers' documented installation method points npm at the SheetJS registry or a tarball URL rather than the public registry:
npm install https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
or by pinning a specific patched version tarball from the same CDN. After installing, verify what actually resolved:
npm ls xlsx
If it still shows 0.18.5, your install pulled from the public registry and you are not patched, regardless of what your package.json version range says.
Why this matters for scanners and audits
Because the vulnerable 0.18.5 is what most projects have, npm audit and dependency scanners routinely flag xlsx in Node projects. Teams often see the alert, run npm update, watch nothing change, and assume the tool is wrong. It is not; the registry genuinely has no newer version to update to. The correct remediation is switching the install source to the CDN tarball, which is exactly the kind of non-obvious fix worth documenting for your team.
This is also a good argument for software composition analysis over eyeballing package.json. A scanner resolves the actual installed version and matches it against advisories, so it will tell you that the xlsx in your lockfile is the vulnerable 0.18.5 even when the range looks permissive. An SCA tool such as Safeguard surfaces both the finding and the fixed version, so you know the target you are aiming for.
Safe usage regardless of version
Even on a patched build, harden the way you parse spreadsheets, because parsers of complex formats are a perennial source of new bugs:
- Only read what you must. If a feature does not require reading untrusted files, use xlsx in write-only mode and both CVEs above become irrelevant to that path.
- Constrain input. Enforce file-size limits and reject unexpected formats before handing bytes to the parser, which blunts ReDoS and memory-exhaustion attempts.
- Guard against prototype pollution downstream. Do not blindly merge parsed spreadsheet data into objects with recursive extend/merge functions; that is often the step that turns a polluted prototype into real impact.
- Isolate heavy parsing. Run large or untrusted parsing in a worker so a stalled event loop from a pathological file does not take down the whole service.
Should you keep using it?
Yes, with eyes open. SheetJS is a capable, actively developed library, and the CVEs have documented fixes. The friction is purely distribution: the patched code lives on the CDN, not the npm registry, so your install command and your understanding of scanner alerts have to account for that. Alternatives exist (ExcelJS and others) if the CDN-based install does not fit your pipeline, but for many teams the pragmatic move is to point the install at the patched tarball and move on. The Safeguard Academy covers how to read dependency advisories like these and confirm a fix actually landed.
FAQ
Is the npm xlsx package safe to use?
It can be, but the version on the public npm registry (0.18.5) is vulnerable to prototype pollution (CVE-2023-30533) and ReDoS (CVE-2024-22363). The patched versions are distributed through the SheetJS CDN, not npm, so a normal npm install xlsx leaves you unpatched.
Why does npm update xlsx not fix the vulnerabilities?
Because the last release published to the public npm registry predates the fixes, there is no newer version there to update to. The patched releases (0.19.3, 0.20.2, and later) are published only via the SheetJS CDN, so you must change your install source, not just run an update.
How do I install a patched xlsx version?
Install from the SheetJS CDN tarball, for example npm install https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz, or pin a specific patched version tarball from the same source. Then run npm ls xlsx to confirm the patched version actually resolved.
Are the xlsx CVEs a problem if I only export spreadsheets?
Largely no. Both CVE-2023-30533 and CVE-2024-22363 are triggered when reading a crafted, untrusted file. A write-only or export workflow that never parses attacker-controlled spreadsheets is not exposed to those specific issues, though keeping the library current is still good practice.