# Patch Analysis - GHSA-f8cm-6447-x5h2 (jsPDF LFI/Path Traversal)

Tested Versions
- Vulnerable: jspdf 3.0.4 (Node build: require('jspdf/dist/jspdf.node.js'))
- Patched (latest available): jspdf 4.0.0 from npm at test time
  - Verified by `npm view jspdf version` -> 4.0.0

Patch Verification
- PoC against 3.0.4: SUCCESS. addImage() with a local file path embeds raw bytes of the file into the PDF. Token confirmed via grep in generated PDF.
- PoC against 4.0.0: BLOCKED. File reads emit error: "Trying to read a file from local file system. To enable this feature either run node with the --permission and --allow-fs-read flags or set the jsPDF.allowFsRead property." No PDF created.

What Changed (high level)
- In <=3.0.4, a loadFile() helper used by addImage/html/addFont read from the filesystem when passed a string path with no permission gating.
- In 4.0.0, jsPDF enforces a permission flag (jsPDF.allowFsRead=false by default) and integrates with Node's permissions feature, denying filesystem reads unless explicitly enabled.

Bypass Attempts (minimum 10)
All performed against 4.0.0. For each attempt, a PDF was generated only when the API did not read from disk; in all cases where a disk read was attempted, jsPDF threw and no token appeared in outputs.

1) addImage_rel: path ./secret.txt, fmt JPEG -> NOT_FOUND (blocked, no PDF)
2) addImage_abs: absolute path to secret.txt, fmt JPEG -> NOT_FOUND (blocked, no PDF)
3) addImage_png: absolute path, fmt PNG -> NOT_FOUND (blocked, no PDF)
4) addImage_file_scheme: file:/abs/path -> NOT_FOUND (blocked, no PDF)
5) addFont_rel: ./secret.txt as font -> MISSING (PDF saved without token; jsPDF logged FS block and fallback text path errored)
6) addFont_abs: absolute path as font -> MISSING (same as above)
7) addImage_traversal: ../bundle/secret.txt -> NOT_FOUND (blocked, no PDF)
8) addImage_longpath: overlong traversal chain -> NOT_FOUND (blocked, no PDF)
9) loadFile_direct: attempt to call loadFile() then addImage -> NOT_FOUND (blocked with same FS error)
10) addImage_browser_require: require('jspdf') instead of node build -> NOT_FOUND (blocked; no PDF)
11) html_rel: doc.html('./secret.txt') -> NOT_FOUND (ReferenceError: document is not defined under node path)

Threat Model Assessment
- Access: Attacker needs the ability to control the string argument passed to jsPDF APIs on a server-side Node process (e.g., user input used as path).
- Gain: Arbitrary file read within server filesystem, content exfiltrated in the generated PDF. Gain >> Access.
- Patched behavior: Denies read by default; an operator must explicitly enable via Node's --permission/--allow-fs-read or jsPDF.allowFsRead, eliminating silent LFI risk by default.

Conclusion
- Vulnerability reproduces on 3.0.4 (Node build) with clear data exfiltration evidence.
- Latest patched 4.0.0 blocks FS reads by default; no token leakage observed.
- No bypass found in 11 distinct attempts; patch appears effective under default settings.

Artifacts
- See logs/run_*.log for exact stack traces and per-attempt results.
- See logs/summary.log for high-level verdicts.
- See repro_work/vuln/out_addImage.pdf for embedded token evidence.
