The html-pdf package still installs and still runs, which is the problem. It renders through PhantomJS, its maintainer archived the repository and marked it deprecated on npm, and it carries an unpatched file-read CVE, and none of that stops npm install html-pdf from working today.
One disambiguation, because the name invites it. This is html-pdf, the PhantomJS-based package, not html-pdf-node, a separate Puppeteer wrapper with a different engine and a different risk profile, and a lot of comparison content online treats the two as one. IronPDF for Node.js renders the same HTML through a current, patched engine, which is the migration this piece is about.
Full disclosure. We build IronPDF for Node.js at Iron Software, and this read looks at where html-pdf's archived engine and unpatched CVE cost a team and where IronPDF renders the same HTML on a maintained engine.
What html-pdf got right
html-pdf earned its place by being simple. The whole call was about as short as the task gets.
const pdf = require("html-pdf");
const html = "<h1>Invoice #1042</h1><p>Total due: $250.00</p>";
pdf.create(html).toFile("invoice.pdf", (err, res) => {
if (err) return console.error(err);
});
Before headless Chrome was an option, HTML-to-PDF in Node was hard, and this API made it approachable. It is MIT-licensed, and it served a large number of production applications reliably for years, a track record that does not disappear because the project has since been retired. Most codebases still referencing it were written by developers who made a well-founded decision with the tools available at the time. What changed is the project behind the API, not the appeal of it.
An archived engine and an unpatched CVE
The engine is the first problem. html-pdf renders through PhantomJS, a headless browser that was itself deprecated years ago, so it predates modern CSS and lays out flexbox and grid the way a browser from another era would, and a page built with modern layout can come out visibly broken. No library option changes that, because the engine is what it is.
The project is the second. Its npm listing marks it deprecated with an explicit message to migrate to a modern renderer, the GitHub repository is archived, and its own description states it is no longer maintained. That is the maintainer's own assessment, not an outside reading, so there is no one to report an issue to and no release coming.
The third is CVE-2019-15138, an arbitrary file-read vulnerability, and because the project is archived it will never be patched. html-pdf renders whatever HTML it is handed, and PhantomJS honours a file:/// URL the same way it honours a remote one, so an XMLHttpRequest at a local path can pull file contents into the page being converted and out through the resulting PDF. If any of that HTML comes from user input, a comment field, an uploaded template, or a print-this-page feature built from user data, the path is reachable today. The last stable release shipped in May 2021, with nothing since.
None of that is a knock on what the library was. A project reaching the end of its life is not a failure, and PhantomJS itself was deprecated by its own maintainers years before this wrapper followed. It is a statement of where the package is now, in the maintainer's own words, and a reason to move rather than a verdict on the years it worked.
html-pdf and IronPDF for Node.js, side by side
| Capability | html-pdf | IronPDF for Node.js |
|---|---|---|
| Rendering engine | PhantomJS, deprecated | Current Chromium, PdfDocument.fromHtml
|
| Modern CSS (flexbox, grid) | Renders incorrectly | Full support |
| Known CVE in own code | CVE-2019-15138, unpatched | None found |
| Last stable release | May 2021 | August 2026 |
| HTML to PDF | pdf.create |
Supported |
Table 1. html-pdf and IronPDF for Node.js across the engine and security questions, from the package's own npm listing, GitHub repository, and the CVE record.
The same HTML on a maintained engine
IronPDF renders the same HTML through a current Chromium build the vendor keeps patched, so modern CSS lays out the way a browser shows it and a newly found issue has a maintainer behind it.
import { PdfDocument } from "@ironsoftware/ironpdf";
const invoice = await PdfDocument.fromHtml(
"<h1>Invoice #1042</h1><p>Total due: $250.00</p>"
);
await invoice.saveAs("invoice.pdf");
That is one call from HTML to a saved file, on an engine that receives fixes rather than one that stopped shipping in 2021. The migration is usually smaller than it looks, since the HTML and CSS you already render does not change, only the call producing the PDF from it. The guide on HTML to PDF on a maintained engine covers the migration in full.
Moving off an archived engine
The one case for html-pdf is a static internal tool whose HTML is written entirely by your own team, never touches user input, and runs on a server already built around it. That covers few live apps, though, since any user-supplied HTML makes the file-read CVE reachable, and modern CSS already renders wrong on PhantomJS either way.
If your app is still calling html-pdf today, the choice is between staying on an archived package with an unpatched CVE and moving to IronPDF for Node.js, which covers the same HTML-to-PDF job on an engine that is still maintained. That decision is one the package's own maintainer already made public, so the real question is not whether to move but which maintained renderer to move to.
Is your html-pdf usage behind fully trusted HTML, or could any of it come from a user? Tell us in the comments, that answer decides how urgent this one is.
html-pdf is an open-source project distributed under the MIT licence, and is not affiliated with Iron Software. The details above are drawn from the package's own npm listing, GitHub repository, and the CVE record. If something has changed since, correct us in the comments.
Top comments (0)