Common Path Traversal in Pdf Reader Apps: Causes and Fixes
Path traversal appears when an application interprets a user‑supplied path without enough validation, allowing the path to reference files outside the intended directory. In PDF readers this happens f
What Causes Path Traversal in PDF Reader Apps
Path traversal appears when an application interprets a user‑supplied path without enough validation, allowing the path to reference files outside the intended directory. In PDF readers this happens for several low‑level reasons:
| Root Cause | Typical Origin in PDFs | Why It Breaks | Example API |
|---|---|---|---|
| Uncanonicalized relative paths | ../../../../../../etc/passwd in an attachment | The OS resolves the path before the app checks it | FileInputStream |
| Hard‑coded base directories | baseDir = "/data/user/0/com.example.reader/files" | No runtime check forces the file to stay inside the sandbox | File |
| Missing path normalization | ..\\..\\..\\..\\..\\secret.txt on Windows | Backslashes are treated literally, bypassing the sandbox | Path |
| JavaScript execution | /JavaScript << /S /JavaScript /JS (app.openDoc("../../secret.pdf")) >> | The JS engine resolves local paths relative to the PDF’s location | app.openDoc |
| Embedded file objects | /EF << /F /file1 /UF /file1 >> with file1 pointing to ../../config.xml | The reader loads the embedded file as a plain file | PDDocument |
| URI actions | /URI (file://../../../../../../../../etc/passwd) | The browser component treats the URI as a local file path | Desktop.getDesktop().browse |
| OpenAction | /OpenAction << /S /JavaScript /JS (#doc.getFile("../../../secret.txt")) >> | The PDF spec allows arbitrary actions on open | PDDocument |
In all cases the PDF reader trusts the input path, concatenates it with the base directory, and performs file I/O. The operating system’s file system permissions may still allow the read/write, especially on Android where apps can request broad storage permissions for compatibility.
---
Real‑World Impact
Path traversal in PDF readers is more than a curiosity—it translates directly into user‑facing failures and revenue loss:
| Impact | Evidence | Consequence |
|---|---|---|
| Data exposure | Users report that opening a PDF from a corporate email reveals the device’s keystore files. | Privacy breach, regulatory fines. |
| Crashes & ANRs | 3.5‑star reviews on Google Play mention “app crashes on PDFs with images.” | Negative ratings, lower rankings. |
| Unauthorized file modification | A PDF with a JavaScript that writes to ../../../../../../../../etc/hosts was reported on Reddit. | System instability, malware propagation. |
| Reputation damage | A case study from 2022 showed a PDF reader with 30 % more negative reviews after a path traversal incident. | Uninstalls, loss of market share. |
| Revenue loss | One developer lost ~$12k in monthly subscriptions after a vulnerability led to a 15 % churn spike. | Direct financial impact. |
These incidents illustrate that path traversal is not purely academic; it can trigger data leaks, crashes, and erode user trust.
---
Common Manifestations in PDF Reader Apps
- Embedded File Paths
PDF’s /EF entries reference a file that resolves outside the sandbox. The reader loads it as a normal file, potentially exposing secrets.
- OpenAction JavaScript
The OpenAction field contains a script that calls app.openDoc("../../../../../../../../../../etc/passwd"), which the reader executes automatically on load.
- URI Actions with File Scheme
The PDF contains a link that uses the file:// scheme and points to ../../../../../../../../../../etc/passwd. The internal browser component treats it as a local file.
- Attachment Name Manipulation
Attachments can carry names like ../../../../../../../../data/secret.txt. When the reader saves the attachment, it writes outside the designated directory.
- JavaScript File System Access
A script inside the PDF uses app.execMenuItem("FileOpen") with a path argument that includes traversal sequences.
- Action Objects with
/S /URI
A link labeled “Open Settings” points to file://../../../../../../../../data/settings.json. The reader opens it without sanitization.
- Redirection via
OpenAction+GoToR
The PDF opens an external PDF file located outside the app’s storage, using a relative path that climbs up the directory tree.
Each manifestation exploits a different part of the PDF specification, but all converge on the same flaw: an unchecked path resolution.
---
How to Detect Path Traversal
| Tool | Technique | What to Look For |
|---|---|---|
| SUSATest (APK/Web URL) | Auto‑explore without scripts; persona‑based testing | Crashes on PDF load, unexpected file reads, permission escalation |
| Static Analysis (FindBugs, PMD) | Scan for FileInputStream, Path.resolve, Desktop.browse with user data | Hard‑coded paths, unchecked string concatenations |
| Dynamic Fuzzing (Burp Suite, OWASP ZAP) | Inject PDFs with crafted paths; observe system calls | File I/O outside sandbox, crash logs |
| Android Logcat | Monitor File operations during PDF open | open("/data/user/.../../etc/passwd") |
| CI/CD Integration (GitHub Actions + SUSATest) | Run SUSATest on every build; parse JUnit XML | Failures flagged as “Security: Path Traversal” |
SUSATest’s persona engine is particularly effective: the eager and adversarial personas trigger PDFs with extreme paths, while the business persona verifies that the app still opens legitimate documents. The platform’s cross‑session learning will flag repeated traversal attempts across builds, giving a clear trend of vulnerability regression.
---
Fixing Each Example
- Embedded File Paths
*Check*: Canonicalize the path before loading.
Path base = Files.createDirectories(Paths.get(appDir));
Path target = base.resolve(attachment.getFileName()).normalize();
if (!target.startsWith(base)) throw new SecurityException();
- OpenAction JavaScript
*Check*: Strip or sandbox JavaScript.
pdfDocument.getOpenAction().setJavaScript(null); // disable on load
- URI Actions with File Scheme
*Check*: Reject file:// URIs entirely.
if (uri.getScheme().equals("file")) throw new IllegalArgumentException();
- Attachment Name Manipulation
*Check*: Validate attachment names against a whitelist.
if (!attachmentName.matches("[\\w\\-.]+")) throw new SecurityException();
- JavaScript File System Access
*Check*: Disable file system APIs in the JS engine.
jsEngine.getBindings().remove("app"); // remove dangerous bindings
- Action Objects with
/S /URI
*Check*: Enforce HTTPS scheme only, or resolve relative paths to base dir.
if (!uri.getScheme().equals("https")) throw new SecurityException();
- Redirection via
OpenAction+GoToR
*Check*: Verify the target PDF’s path stays within the app’s storage.
Path target = base.resolve(goToR.getFile()).normalize();
if (!target.startsWith(base)) throw new SecurityException();
These fixes follow a common pattern: canonicalize and compare the resolved path against a known safe base, and reject any path that escapes. When Java
Test Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free