From 2af191cf8234f0a8367ea3279812d6316465a59e Mon Sep 17 00:00:00 2001 From: jedarden Date: Sun, 5 Jul 2026 15:48:33 -0400 Subject: [PATCH] docs(bf-5w2us): document PDF JavaScript action structure research Research on PDF JavaScript action dictionary structure for TH-04 threat model: - Minimal action dictionary: /S /JavaScript + /JS (code) - Attachment points: catalog /OpenAction, page /AA, annotation /A, form field /AA - JS string formats: literal text, hex-encoded, or stream - Required parent keys and trigger events - Security considerations and detection strategy Addresses all acceptance criteria for bead bf-5w2us. --- notes/bf-5w2us.md | 302 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 notes/bf-5w2us.md diff --git a/notes/bf-5w2us.md b/notes/bf-5w2us.md new file mode 100644 index 0000000..7d9034e --- /dev/null +++ b/notes/bf-5w2us.md @@ -0,0 +1,302 @@ +# PDF JavaScript Action Structure Research + +**Bead:** bf-5w2us +**Date:** 2025-07-05 +**Task:** Research PDF JavaScript action structure for TH-04 threat model implementation + +## Overview + +This research documents the minimal PDF structure required for valid JavaScript actions, based on the PDF 1.7 specification (ISO 32000-1:2008) and practical examples from security research. JavaScript actions in PDFs are a known attack vector (TH-04) but are useful for legitimate interactivity. pdftract's approach is to **detect and report** JavaScript actions, never execute them. + +## Minimal JavaScript Action Dictionary + +A JavaScript action in a PDF requires **two mandatory keys**: + +``` +<< /S /JavaScript /JS (JavaScript code here) >> +``` + +### Required Keys + +1. **`/S`** (Name) - Action type specification + - Value: `/JavaScript` + - Required: Yes + - Purpose: Identifies this action dictionary as containing JavaScript code + +2. **`/JS`** (Text String or Stream) - JavaScript content + - Value: Text string OR text stream containing JavaScript code + - Required: Yes + - Format options: + - **Text string**: `(JavaScript code)` or `(JavaScript\ code\ with\ escapes)` or `` + - **Text stream**: `stream\nJavaScript code\nendstream` + - Purpose: Contains the actual JavaScript to execute + +### Example Minimal JavaScript Action + +``` +<< /S /JavaScript /JS (app.alert('Hello World!')) >> +``` + +## JavaScript Action Placement Locations + +JavaScript actions can be attached at multiple levels in the PDF object tree: + +### 1. Document Catalog Level + +#### `/OpenAction` (Document Open Action) +- **Location**: Catalog dictionary (`/Type/Catalog`) +- **Execution**: Automatically when PDF is opened +- **Required parent key**: `/OpenAction` +- **Example**: + ``` + 7 0 obj + << + /Type/Catalog + /Pages 6 0 R + /OpenAction << /S /JavaScript /JS (app.alert("pwn")) >> + >> + endobj + ``` + +### 2. Page Level + +#### `/AA` (Additional Actions) Dictionary +- **Location**: Page dictionary (`/Type/Page`) +- **Execution**: On specific page events (open, close, etc.) +- **Required parent key**: `/AA` +- **Trigger keys**: `/O` (open), `/C` (close), etc. +- **Example**: + ``` + 1 0 obj + << + /Type/Page + /MediaBox[0 0 612 792] + /Parent 0 0 R + /Contents 2 0 R + /AA << + /O << /S /JavaScript /JS (app.alert('page_open')) >> + >> + >> + endobj + ``` + +### 3. Annotation Level + +#### `/A` (Action) on Link Annotation +- **Location**: Annotation dictionary (`/Type/Annot /Subtype/Link`) +- **Execution**: When annotation is clicked/activated +- **Required parent key**: `/A` +- **Example**: + ``` + 5 0 obj + << + /Type/Annot + /Subtype/Link + /Rect[100 600 200 620] + /A << /S /JavaScript /JS (app.alert('annot_action')) >> + >> + endobj + ``` + +### 4. Form Field Level + +#### `/AA` on Interactive Form Fields +- **Location**: Form field dictionary (Widget annotation, Field dictionary) +- **Execution**: On field-specific events (focus, blur, validate, calculate, etc.) +- **Required parent key**: `/AA` +- **Trigger keys**: `/F` (format), `/V` (validate), `/K` (keystroke), `/C` (calculate) + +## JavaScript String Formats + +The `/JS` entry can contain JavaScript in three formats: + +### 1. Literal Text String +``` +/JS (app.alert('Hello')) +``` +- Simple parentheses-delimited string +- Special characters must be escaped with backslash `\( \) \\` +- Limited to ASCII (use hex or octal escapes for non-ASCII) + +### 2. Hexadecimal-Encoded String +``` +/JS <6170702E616C657274282748656C6C6F2729> +``` +- Encodes bytes as hex pairs +- Useful for binary data or Unicode characters +- Case-insensitive (6a = 6A) + +### 3. Text Stream +``` +/JS 10 0 R +... +10 0 obj +<< /Length 44 >> +stream +// Multi-line +// JavaScript code +app.alert('Hello'); +endstream +endobj +``` +- JavaScript stored as indirect object reference +- Can contain arbitrary content including newlines, quotes +- Useful for longer scripts + +## Parent Keys and Attachment Points + +### Required Parent Key Summary + +| Attachment Point | Parent Key | Trigger | +|-----------------|-----------|---------| +| Document catalog | `/OpenAction` | Document opens | +| Page | `/AA /O` | Page opens | +| Page | `/AA /C` | Page closes | +| Annotation (Link) | `/A` | Annotation clicked | +| Annotation (Widget) | `/AA /K` | Keystroke | +| Annotation (Widget) | `/AA /F` | Format | +| Annotation (Widget) | `/AA /V` | Validate | +| Annotation (Widget) | `/AA /C` | Calculate | +| Bookmark | `/A` | Bookmark clicked | + +## Complete Minimal PDF Example + +Here's a minimal valid PDF with JavaScript at all three attachment points: + +``` +%PDF-1.4 + +1 0 obj +<< +/Type/Page +/MediaBox[0 0 612 792] +/Parent 3 0 R +/Resources<< +/Font<< +/F1<> +>> +>> +/Contents 2 0 R +/AA<< +/O<> +>> +>> +endobj + +2 0 obj +<< +/Length 44 +>> +stream +BT +/F1 12 Tf +100 700 Td +(Page 0) Tj +ET +endstream +endobj + +3 0 obj +<< +/Type/Pages +/Count 1 +/Kids[1 0 R] +>> +endobj + +4 0 obj +<< +/Type/Catalog +/Pages 3 0 R +/OpenAction<> +>> +endobj + +xref +0 5 +0000000000 65535 f +0000000009 00000 n +0000000247 00000 n +0000000348 00000 n +0000000419 00000 n +trailer +<< +/Size 5 +/Root 4 0 R +>> +startxref +520 +%%EOF +``` + +## Security Considerations (TH-04) + +### Attack Vector +JavaScript in PDFs can execute arbitrary code in the Acrobat JavaScript context, including: +- File system access (limited but present) +- Network requests +- Information disclosure +- Social engineering (fake alerts, prompts) + +### Detection Strategy +pdftract should: +1. **Never execute** embedded JavaScript +2. **Parse and detect** JavaScript actions at all attachment points +3. **Report presence** via `JAVASCRIPT_PRESENT` diagnostic (info-level) +4. **Surface metadata** in JSON output: `metadata.javascript_actions[]` +5. **Include location** (catalog/page/annotation), trigger, and code snippet + +### Test Fixtures +The existing fixture `tests/fixtures/security/embedded-js.pdf` demonstrates all three attachment points: +- Catalog `/OpenAction` → `app.alert("pwn")` +- Page 0 `/AA /O` → `app.alert('page_open')` +- Page 1 annotation `/A` → `app.alert('annot_action')` + +## PDF Specification References + +- **PDF 1.7 Reference** (ISO 32000-1:2008) + - Section 12.6: Interactive Features (Actions) + - Section 12.6.4: Action Types + - JavaScript actions introduced in PDF 1.3 + +- **Additional Actions Dictionary** (`/AA`) + - Defined in PDF 1.2+ + - Associates actions with specific trigger events + - Prohibited in PDF/A-1 for archival stability + +## Sources + +- [PDF Reference, version 1.7](https://opensource.adobe.com/dc-acsdk-docs/pdfstandards/pdfreference1.7old.pdf) - Adobe Open Source +- [Portable document format — Part 1: PDF 1.7 (ISO 32000-1:2008)](https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf) - Adobe Open Source +- [Notes for Analysing Malicious PDF Documents](https://prtksec.github.io/posts/MA_PDF_Notes/) - Pratik Patel +- [How PDF forms use JavaScript for validation](https://blog.idrsolutions.com/how-pdf-forms-use-javascript-for-validation/) - IDR Solutions +- [Corkami PDF Documentation](https://github.com/corkami/docs/blob/master/PDF/PDF.md) - Ange Albertini +- [PDF Injection Security](https://hacktricks.wiki/en/pentesting-web/xss-cross-site-scripting/pdf-injection.html) - HackTricks +- [PDF/A-1 Compliance (6.6.2)](https://www.soliddocuments.com/iso-19005-1-compliance.htm?subject=6.6.2) - Solid Documents + +## Implementation Notes for pdftract + +1. **Parser**: When traversing PDF dictionaries, check for: + - `/OpenAction` in catalog + - `/AA` in any object (page, annotation, form field) + - `/A` in annotations + +2. **Action detection**: When action dictionary found, check if `/S` equals `/JavaScript` + +3. **Code extraction**: Extract `/JS` value (text string, hex string, or stream reference) + +4. **Reporting**: Emit `JAVASCRIPT_PRESENT` diagnostic with: + - Location path (e.g., `/Root/OpenAction`, `/Pages/Kids[0]/AA/O`) + - Trigger event type + - Code snippet (first 100 chars, sanitized) + +5. **JSON output**: Add to `metadata.javascript_actions[]` array with structured info + +## Verification Criteria + +- [PASS] Documented minimal JavaScript action dictionary structure (`/S /JavaScript` + `/JS`) +- [PASS] Identified all attachment points (catalog `/OpenAction`, page `/AA`, annotation `/A`, form field `/AA`) +- [PASS] Understood JS string formats (literal, hex, stream) +- [PASS] Noted required parent keys and trigger events +- [PASS] Located existing test fixture with embedded JavaScript +- [PASS] Cited all sources from research