Written by
Published on
May 15, 2025
Topic
Engineering
During a recent penetration test, we found a vulnerability with PDF JavaScript execution in Firefox’s native PDF viewer. This specific vulnerability is known as CVE-2024-4367 and affects Firefox browser versions 126 and under.
The vulnerability involves users being able to inject JavaScript into a PDF that runs in the browser runtime.

Context on Firefox’s PDF viewer
Firefox maintains PDF.js, a common tool that web applications can use to render PDFs directly in webpages, like with React PDF Viewer. They also use PDF.js to display PDFs that you may download across the internet, so you don’t have to download extra software just to view PDFs.
Our pentester linked a really great resource that includes 11 vulnerable PDFs. All the PDFs will basically try to inject JavaScript using various techniques from different CVEs. A few of them were used to find vulnerabilities in our own application, which could potentially cause code injection and compromise our users.

Handling PDF vulnerabilities in your web app
React PDF viewer actually has some pretty sane defaults. All script execution is disabled by default. This has been circumvented in the past, so keeping your PDF web renderer up to date and using Dependabot to detect vulnerable versions you have installed is crucial.
An additional bonus step that I think everyone should take is to santizie PDFs. There are some paid services which claim to be the best, but there are also some free tools that work just fine for most use cases.
All three of these free tools will sanitize your PDFs. In practice, you just need to run these tools in your backend application, for example:
Ideally, this is done before uploading your PDFs to your storage provider like AWS S3.
After implementing our mutools cleaner utility, I was still able to upload payload1.pdf from the repository I linked earlier, and to my surprise, the alert(1) was still executing. Here is the actual code of the PDF where the injection is happening
This was quite a bit of a headache to figure out. Chrome did not display the alert, only Firefox. I wasn’t testing on a vulnerable version of Firefox. I tried about five different PDF sanitizer tools and none of them would sanitize this. I even opened an issue on Mozilla’s PDF.js repository (which I closed shortly after I did more research).
What does Mozilla say about JavaScript execution in PDF.js?
After a lot of Google searches and looking through GitHub issues and StackOverflow, I finally found a link to an article by Mozilla.
Implementing form filling and accessibility in the Firefox PDF viewer
This article has a section about “Safely Executing JavaScript within PDFs” which can be paraphrased to read
JavaScript in PDFs can be used for many things, but is most commonly used to validate data entered by the user or automatically calculate formulas. We settled on using a ComponentUtils.Sandbox for the Firefox built-in viewer. ComponentUtils.Sandbox has been used for years now in WebExtensions, so this implementation is battle tested and very safe.
This process basically involves the PDF viewer collecting fields that execute JS, copying them to a sandbox, and then executing them.
What even is a Sandbox?
A sandbox is typically an execution runtime that is stripped from APIs that can call external services. In Firefox’s case, it removes XHR
, window
, and Components
among others. This essentially cuts off access to network requests, accessing window objects in the webpage, and prevents access to Firefox’s built‐in JavaScript engine (SpiderMonkey).
It’s a feature… not a bug
Sandboxing JavaScript is safe enough. I now needed to make sure that payload1.pdf was actually executing in a sandbox. We can update the payload like so
The payload essentially just looks like this:
After updating the payload, we can confirm the injection is actually running in sandboxed JS.

Conclusion
This information can be very useful for both pentesters and web developers. Pentesters should be aware that the Firefox PDF viewer actually allows script execution. Chrome only allows a small subset of script execution through their custom API, Safari does not allow JavaScript execution at all, and other browsers vary.
For pentesters, it may be exciting to see the alert pop up and you think you’ve found a vulnerability, but you should always check if the execution is sandboxed (see payload above) before you report an issue.
For web developers, it’s important to keep your dependencies up to date and have a service that sanitizes PDFs. It is your responsibility to keep your users safe.
Jack Novotny
Frontend Engineer @ Oneleet
Full-stack engineer specializing in Frontend React development. I love balancing velocity, quality, and security. Based in Denver, CO.
Check All Other Articles
Continue reading

Jack Novotny
Practical Web Security in React
May 12, 2025
Most frontend engineers have heard of the OWASP top 10, and I would say fewer could list all 10. But working on React frontends in your actual day-to-day work goes beyond just knowing about these vulnerabilities. We take a lot of things for granted that React…

Mona Zimmermann
Achieve EU DORA Compliance: A Clear Path for SMEs
Dec 16, 2024
Data security doesn’t just protect your secrets from prying eyes—it’s the foundation for securing your business’s future. For VC-backed startups, it’s not just…

Koby Conrad
Data Security: Threats, Solutions, and Best Practices
Sep 24, 2024
Data security doesn’t just protect your secrets from prying eyes—it’s the foundation for securing your business’s future. For VC-backed startups, it’s not just…