mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
fix(sanitize): fix JavaScript handling, embedded file sanitization (#4652)
# Description of Changes ### Fixes - Added document-level JavaScript removal: Now removes OpenAction and catalog additional actions (WC, WS, DS, WP, DP) that execute on document open, save, print, and close events - Added page-level JavaScript removal: Removes page open/close actions (O, C) that were previously missed - Added annotation additional actions removal: Removes all 10 annotation event handlers (Bl, D, E, Fo, PC, PI, PO, PV, U, X) for mouse/focus events - Fixed embedded file removal: Corrected implementation to use `catalog.getNames().setEmbeddedFiles(null)` instead of incorrectly targeting page resources ### Verification: Before (after embedded file "removal"): <img width="706" height="671" alt="image" src="https://github.com/user-attachments/assets/7d10e1ba-78bc-4094-b28a-0eae3613db3c" /> After: <img width="706" height="671" alt="image" src="https://github.com/user-attachments/assets/b278c2a6-1605-483f-b39c-1c3aa047acc2" /> <!-- Please provide a summary of the changes, including: - What was changed - Why the change was made - Any challenges encountered Closes #(issue_number) --> --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [x] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
This commit is contained in:
parent
085b8795d5
commit
06efab5cb2
@ -2,22 +2,25 @@ package stirling.software.SPDF.controller.api.security;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.pdfbox.cos.COSDictionary;
|
import org.apache.pdfbox.cos.COSDictionary;
|
||||||
import org.apache.pdfbox.cos.COSName;
|
import org.apache.pdfbox.cos.COSName;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
|
||||||
import org.apache.pdfbox.pdmodel.PDPage;
|
import org.apache.pdfbox.pdmodel.PDPage;
|
||||||
import org.apache.pdfbox.pdmodel.PDPageTree;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDResources;
|
|
||||||
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.action.PDAction;
|
import org.apache.pdfbox.pdmodel.interactive.action.PDAction;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript;
|
import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.action.PDActionLaunch;
|
import org.apache.pdfbox.pdmodel.interactive.action.PDActionLaunch;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI;
|
import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.action.PDDocumentCatalogAdditionalActions;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.action.PDFormFieldAdditionalActions;
|
import org.apache.pdfbox.pdmodel.interactive.action.PDFormFieldAdditionalActions;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.action.PDPageAdditionalActions;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
|
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationFileAttachment;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
|
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
|
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
|
||||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||||
@ -34,6 +37,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
|||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.security.SanitizePdfRequest;
|
import stirling.software.SPDF.model.api.security.SanitizePdfRequest;
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
@ -43,6 +47,7 @@ import stirling.software.common.util.WebResponseUtils;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/security")
|
@RequestMapping("/api/v1/security")
|
||||||
@Tag(name = "Security", description = "Security APIs")
|
@Tag(name = "Security", description = "Security APIs")
|
||||||
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class SanitizeController {
|
public class SanitizeController {
|
||||||
|
|
||||||
@ -99,7 +104,7 @@ public class SanitizeController {
|
|||||||
GeneralUtils.generateFilename(inputFile.getOriginalFilename(), "_sanitized.pdf"));
|
GeneralUtils.generateFilename(inputFile.getOriginalFilename(), "_sanitized.pdf"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sanitizeJavaScript(PDDocument document) throws IOException {
|
private static void sanitizeJavaScript(PDDocument document) throws IOException {
|
||||||
// Get the root dictionary (catalog) of the PDF
|
// Get the root dictionary (catalog) of the PDF
|
||||||
PDDocumentCatalog catalog = document.getDocumentCatalog();
|
PDDocumentCatalog catalog = document.getDocumentCatalog();
|
||||||
|
|
||||||
@ -118,16 +123,30 @@ public class SanitizeController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PDPage page : document.getPages()) {
|
if (catalog.getOpenAction() instanceof PDActionJavaScript) {
|
||||||
for (PDAnnotation annotation : page.getAnnotations()) {
|
catalog.setOpenAction(null);
|
||||||
if (annotation instanceof PDAnnotationWidget widget) {
|
}
|
||||||
PDAction action = widget.getAction();
|
|
||||||
if (action instanceof PDActionJavaScript) {
|
PDDocumentCatalogAdditionalActions catalogActions = catalog.getActions();
|
||||||
widget.setAction(null);
|
if (catalogActions != null) {
|
||||||
|
if (catalogActions.getWC() instanceof PDActionJavaScript) {
|
||||||
|
catalogActions.setWC(null);
|
||||||
|
}
|
||||||
|
if (catalogActions.getWS() instanceof PDActionJavaScript) {
|
||||||
|
catalogActions.setWS(null);
|
||||||
|
}
|
||||||
|
if (catalogActions.getDS() instanceof PDActionJavaScript) {
|
||||||
|
catalogActions.setDS(null);
|
||||||
|
}
|
||||||
|
if (catalogActions.getWP() instanceof PDActionJavaScript) {
|
||||||
|
catalogActions.setWP(null);
|
||||||
|
}
|
||||||
|
if (catalogActions.getDP() instanceof PDActionJavaScript) {
|
||||||
|
catalogActions.setDP(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
|
PDAcroForm acroForm = catalog.getAcroForm();
|
||||||
if (acroForm != null) {
|
if (acroForm != null) {
|
||||||
for (PDField field : acroForm.getFields()) {
|
for (PDField field : acroForm.getFields()) {
|
||||||
PDFormFieldAdditionalActions actions = field.getActions();
|
PDFormFieldAdditionalActions actions = field.getActions();
|
||||||
@ -147,21 +166,46 @@ public class SanitizeController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (PDPage page : document.getPages()) {
|
||||||
|
PDPageAdditionalActions pageActions = page.getActions();
|
||||||
|
if (pageActions != null) {
|
||||||
|
if (pageActions.getO() instanceof PDActionJavaScript) {
|
||||||
|
pageActions.setO(null);
|
||||||
|
}
|
||||||
|
if (pageActions.getC() instanceof PDActionJavaScript) {
|
||||||
|
pageActions.setC(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sanitizeEmbeddedFiles(PDDocument document) {
|
for (PDAnnotation annotation : page.getAnnotations()) {
|
||||||
PDPageTree allPages = document.getPages();
|
if (annotation instanceof PDAnnotationWidget widget) {
|
||||||
|
PDAction action = widget.getAction();
|
||||||
for (PDPage page : allPages) {
|
if (action instanceof PDActionJavaScript) {
|
||||||
PDResources res = page.getResources();
|
widget.setAction(null);
|
||||||
if (res != null && res.getCOSObject() != null) {
|
}
|
||||||
res.getCOSObject().removeItem(COSName.getPDFName("EmbeddedFiles"));
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sanitizeXMPMetadata(PDDocument document) {
|
private static void sanitizeEmbeddedFiles(PDDocument document) throws IOException {
|
||||||
|
PDDocumentCatalog catalog = document.getDocumentCatalog();
|
||||||
|
PDDocumentNameDictionary names = catalog.getNames();
|
||||||
|
if (names != null) {
|
||||||
|
names.setEmbeddedFiles(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PDPage page : document.getPages()) {
|
||||||
|
List<PDAnnotation> annotations = page.getAnnotations();
|
||||||
|
if (annotations != null && !annotations.isEmpty()) {
|
||||||
|
annotations.removeIf(
|
||||||
|
annotation -> annotation instanceof PDAnnotationFileAttachment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sanitizeXMPMetadata(PDDocument document) {
|
||||||
if (document.getDocumentCatalog() != null) {
|
if (document.getDocumentCatalog() != null) {
|
||||||
PDMetadata metadata = document.getDocumentCatalog().getMetadata();
|
PDMetadata metadata = document.getDocumentCatalog().getMetadata();
|
||||||
if (metadata != null) {
|
if (metadata != null) {
|
||||||
@ -170,7 +214,7 @@ public class SanitizeController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sanitizeDocumentInfoMetadata(PDDocument document) {
|
private static void sanitizeDocumentInfoMetadata(PDDocument document) {
|
||||||
PDDocumentInformation docInfo = document.getDocumentInformation();
|
PDDocumentInformation docInfo = document.getDocumentInformation();
|
||||||
if (docInfo != null) {
|
if (docInfo != null) {
|
||||||
PDDocumentInformation newInfo = new PDDocumentInformation();
|
PDDocumentInformation newInfo = new PDDocumentInformation();
|
||||||
@ -178,7 +222,7 @@ public class SanitizeController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sanitizeLinks(PDDocument document) throws IOException {
|
private static void sanitizeLinks(PDDocument document) throws IOException {
|
||||||
for (PDPage page : document.getPages()) {
|
for (PDPage page : document.getPages()) {
|
||||||
for (PDAnnotation annotation : page.getAnnotations()) {
|
for (PDAnnotation annotation : page.getAnnotations()) {
|
||||||
if (annotation instanceof PDAnnotationLink linkAnnotation) {
|
if (annotation instanceof PDAnnotationLink linkAnnotation) {
|
||||||
@ -191,7 +235,7 @@ public class SanitizeController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sanitizeFonts(PDDocument document) {
|
private static void sanitizeFonts(PDDocument document) {
|
||||||
for (PDPage page : document.getPages()) {
|
for (PDPage page : document.getPages()) {
|
||||||
if (page != null
|
if (page != null
|
||||||
&& page.getResources() != null
|
&& page.getResources() != null
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user