PDFs can run code. Not the JavaScript of a web page — a separate, older dialect with a document-oriented API — but code nonetheless, executing when a document opens, when a field changes, when a page is displayed. It powers the form behaviour people take for granted, and it has been the vehicle for a long series of viewer exploits. This covers what PDF JavaScript can legitimately do, what it cannot, where the risk really sits, and whether you should simply turn it off.
What it is
Acrobat JavaScript is an ECMAScript implementation with a document-specific object model, introduced in the late 1990s and standardised as part of ISO 32000. It is not the browser's JavaScript: there is no DOM, no fetch, no window. There is a Doc object, a Field object, an app object, and a set of methods for manipulating a document and its forms.
Scripts live in several places in a file:
- Document-level scripts, run when the document opens.
/OpenAction, an action triggered on open — which may be a script.- Field-level scripts: on keystroke, on validation, on calculation, on format, on blur.
- Page actions: on page open and page close.
- Annotation actions: on mouse-up, on mouse-enter, and so on for links, buttons and other annotations.
- Bookmark actions.
The proliferation of trigger points is itself part of the security story — a script can be attached in half a dozen places, and inspecting a file means checking all of them.
What it legitimately does
The everyday, boring, useful cases:
Calculations. A total that sums line items, VAT computed from a subtotal, a date field that fills from another. This is the single most common use and it is genuinely valuable — see how to add calculations to a PDF form.
Validation. Rejecting an out-of-range number, requiring a well-formed email, checking a date is not in the past. Covered in how to add validation to a PDF form.
Formatting. Displaying 1234.5 as £1,234.50 while keeping the underlying value numeric.
Conditional behaviour. Showing or hiding fields based on earlier answers, the closest a PDF form gets to a branching questionnaire.
Dynamic stamps. The date-and-name stamps described in how to add a stamp to a PDF are form templates driven by script.
Navigation and interactivity. Buttons that jump, show, hide, print, or submit — see interactive PDFs with JavaScript.
None of this is exotic, and for a business form of any complexity it is close to essential. That is why the feature has not simply been removed.
What it cannot do
Worth stating clearly, because the reputation exceeds the reality. PDF JavaScript, in a modern viewer with default settings, cannot:
- Read or write arbitrary files on your disk. File access is restricted to privileged contexts.
- Launch programs.
/Launchactions exist separately and are blocked or heavily gated. - Make arbitrary network requests.
Net.HTTPand similar are privileged-only. - Access other documents or the rest of your system.
Many of the most powerful methods are marked privileged: they only run in a privileged context — a trusted function, a certified document, or a folder-level script installed by an administrator. In an ordinary document opened by an ordinary user, they throw a security exception.
So the direct capability of a script in an untrusted PDF is modest. The risk lies elsewhere.
Where the risk actually is
The engine is an attack surface. The primary historical danger has never been what the script is permitted to do; it is that running a script at all exercises a large, complex interpreter written in a memory-unsafe language. A long series of Acrobat vulnerabilities followed the same shape: script runs, shapes the heap into a predictable state, then triggers a bug in an unrelated parser — a font, an image, an XFA element — to achieve code execution. Without script, the heap grooming step is much harder and many bugs become impractical to exploit reliably.
This is the real argument for disabling JavaScript: not that a script can hurt you directly, but that it removes the attacker's most convenient tool.
Privilege escalation bugs. Several past vulnerabilities allowed unprivileged script to reach privileged APIs. These are patched as they are found, and finding more is a live research area.
Data exfiltration through form submission. A form's submit action can post field data to a URL. That is a feature, and a document that collects information under a false pretext and submits it elsewhere is a phishing page in document form.
Obfuscation. Script in PDFs is frequently encoded, split across objects, and hidden behind filters, specifically to defeat static analysis. A file that goes to unusual lengths to make its script unreadable is telling you something.
Broader context: malicious PDFs and how to stay safe.
Should you disable it?
For most individuals: yes.
In Acrobat: Preferences → JavaScript → uncheck "Enable Acrobat JavaScript". You can also enable it selectively via the trusted-document and privileged-locations settings, so a specific internal form still works while everything else is inert.
What you lose: calculated totals stop calculating, validation stops validating, conditional fields stop responding, dynamic stamps stop dating themselves. If you fill in complex forms regularly — expenses, tax, procurement — you will notice. If you mostly read documents, you will never notice at all.
A reasonable middle path for an organisation: disable JavaScript globally, and add the specific internal form locations to the privileged-locations list. Users get working internal forms and inert external ones, which matches the actual threat distribution.
Browser viewers make the decision for you. Chrome and Edge run a restricted subset; Firefox's PDF.js implements a limited emulation of the form APIs and no more. This is one of the underrated advantages of reading unexpected attachments in the browser.
Checking a file for script
Before opening something you are unsure about:
pdfid.py suspicious.pdf
reports the counts of /JS, /JavaScript, /AA, /OpenAction, /AcroForm, /EmbeddedFile and /Launch. An invoice with no form fields that nonetheless contains an /OpenAction script deserves scrutiny.
To read the script itself:
qpdf --qdf --object-streams=disable in.pdf readable.pdf
then search the output for /JavaScript. Object streams compress and hide the content; --qdf unpacks everything into readable form. Background: qpdf introduction and PDF internals: objects and streams.
If you build forms with script
Some practical constraints, if you are on the authoring side:
- Keep it minimal. Every script is a support burden across viewers that implement the API to varying degrees. Acrobat is the reference; everything else is partial.
- Do not rely on it for correctness. A validation script is a convenience for the person filling the form, not a guarantee for you. Anyone can submit data that never passed through your script — validate again wherever the data lands.
- Expect it to be disabled. Design the form so that a user with script turned off can still complete and submit it, with the arithmetic done manually if necessary. A form that produces a blank total for security-conscious users is a broken form.
- Never put secrets in it. Script is plainly readable in the file. An API key, an internal URL, or a validation rule you consider confidential is published the moment you distribute the document.
- Consider whether you need a PDF at all. For anything with real branching logic, a web form is better in every dimension — accessibility, validation, data capture, mobile use. PDF forms earn their place when the artefact must be a document: printable, archivable, signable. See making a PDF fillable and PDF form field types explained.
Summary
PDF JavaScript is a restricted, document-scoped scripting environment that powers calculations, validation and conditional forms, and that cannot by itself touch your filesystem or network. Its danger is indirect: it hands attackers an interpreter with which to make other vulnerabilities exploitable. Disabling it in Acrobat costs you interactive form behaviour and removes a meaningful slice of attack surface — a trade most readers should take, and one that authors should design around rather than against.