mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-15 11:00:47 +02:00
url fixes for access issues (#4013)
# Description of Changes This pull request introduces a new SSRF (Server-Side Request Forgery) protection mechanism for URL handling in the application. Key changes include adding a dedicated `SsrfProtectionService`, integrating SSRF-safe policies into HTML sanitization, and extending application settings to support configurable URL security options. ### SSRF Protection Implementation: * **`SsrfProtectionService`**: Added a new service to handle SSRF protection with configurable levels (`OFF`, `MEDIUM`, `MAX`) and checks for private networks, localhost, link-local addresses, and cloud metadata endpoints (`app/common/src/main/java/stirling/software/common/service/SsrfProtectionService.java`). ### Application Configuration Enhancements: * **`ApplicationProperties`**: Introduced a new `Html` configuration class with nested `UrlSecurity` settings, allowing fine-grained control over URL security, including allowed/blocked domains and internal TLDs (`app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java`). [[1]](diffhunk://#diff-1c357db0a3e88cf5bedd4a5852415fadad83b8b3b9eb56e67059d8b9d8b10702R293) [[2]](diffhunk://#diff-1c357db0a3e88cf5bedd4a5852415fadad83b8b3b9eb56e67059d8b9d8b10702R346-R364) * **`settings.yml.template`**: Updated the configuration template to include the new `html.urlSecurity` settings, enabling users to customize SSRF protection behavior (`app/core/src/main/resources/settings.yml.template`). ### HTML Sanitization Updates: * **`CustomHtmlSanitizer`**: Integrated SSRF-safe URL validation into the HTML sanitizer by using the `SsrfProtectionService`. Added a custom policy for validating `img` tags' `src` attributes (`app/common/src/main/java/stirling/software/common/util/CustomHtmlSanitizer.java`). --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] 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) - [ ] I have performed a self-review of my own code - [ ] 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) - [ ] 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. --------- Co-authored-by: a <a> Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com> Co-authored-by: Copilot <[email protected]>
This commit is contained in:
co-authored by
a <a>
pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com>
Copilot
parent
c161000f85
commit
7d6b70871b
+4
-2
@@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import stirling.software.common.configuration.RuntimePathConfig;
|
||||
import stirling.software.common.model.api.converters.EmlToPdfRequest;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.CustomHtmlSanitizer;
|
||||
import stirling.software.common.util.EmlToPdf;
|
||||
import stirling.software.common.util.TempFileManager;
|
||||
import stirling.software.common.util.WebResponseUtils;
|
||||
@@ -37,6 +38,7 @@ public class ConvertEmlToPDF {
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
private final RuntimePathConfig runtimePathConfig;
|
||||
private final TempFileManager tempFileManager;
|
||||
private final CustomHtmlSanitizer customHtmlSanitizer;
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/eml/pdf")
|
||||
@Operation(
|
||||
@@ -103,9 +105,9 @@ public class ConvertEmlToPDF {
|
||||
request,
|
||||
fileBytes,
|
||||
originalFilename,
|
||||
false,
|
||||
pdfDocumentFactory,
|
||||
tempFileManager);
|
||||
tempFileManager,
|
||||
customHtmlSanitizer);
|
||||
|
||||
if (pdfBytes == null || pdfBytes.length == 0) {
|
||||
log.error("PDF conversion failed - empty output for {}", originalFilename);
|
||||
|
||||
+5
-8
@@ -14,9 +14,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import stirling.software.common.configuration.RuntimePathConfig;
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.model.api.converters.HTMLToPdfRequest;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.CustomHtmlSanitizer;
|
||||
import stirling.software.common.util.ExceptionUtils;
|
||||
import stirling.software.common.util.FileToPdf;
|
||||
import stirling.software.common.util.TempFileManager;
|
||||
@@ -30,12 +30,12 @@ public class ConvertHtmlToPDF {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
private final ApplicationProperties applicationProperties;
|
||||
|
||||
private final RuntimePathConfig runtimePathConfig;
|
||||
|
||||
private final TempFileManager tempFileManager;
|
||||
|
||||
private final CustomHtmlSanitizer customHtmlSanitizer;
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/html/pdf")
|
||||
@Operation(
|
||||
summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF",
|
||||
@@ -57,17 +57,14 @@ public class ConvertHtmlToPDF {
|
||||
"error.fileFormatRequired", "File must be in {0} format", ".html or .zip");
|
||||
}
|
||||
|
||||
boolean disableSanitize =
|
||||
Boolean.TRUE.equals(applicationProperties.getSystem().getDisableSanitize());
|
||||
|
||||
byte[] pdfBytes =
|
||||
FileToPdf.convertHtmlToPdf(
|
||||
runtimePathConfig.getWeasyPrintPath(),
|
||||
request,
|
||||
fileInput.getBytes(),
|
||||
originalFilename,
|
||||
disableSanitize,
|
||||
tempFileManager);
|
||||
tempFileManager,
|
||||
customHtmlSanitizer);
|
||||
|
||||
pdfBytes = pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes);
|
||||
|
||||
|
||||
+5
-8
@@ -24,9 +24,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import stirling.software.common.configuration.RuntimePathConfig;
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.model.api.GeneralFile;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.CustomHtmlSanitizer;
|
||||
import stirling.software.common.util.ExceptionUtils;
|
||||
import stirling.software.common.util.FileToPdf;
|
||||
import stirling.software.common.util.TempFileManager;
|
||||
@@ -39,12 +39,12 @@ import stirling.software.common.util.WebResponseUtils;
|
||||
public class ConvertMarkdownToPdf {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
|
||||
private final ApplicationProperties applicationProperties;
|
||||
private final RuntimePathConfig runtimePathConfig;
|
||||
|
||||
private final TempFileManager tempFileManager;
|
||||
|
||||
private final CustomHtmlSanitizer customHtmlSanitizer;
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf")
|
||||
@Operation(
|
||||
summary = "Convert a Markdown file to PDF",
|
||||
@@ -79,17 +79,14 @@ public class ConvertMarkdownToPdf {
|
||||
|
||||
String htmlContent = renderer.render(document);
|
||||
|
||||
boolean disableSanitize =
|
||||
Boolean.TRUE.equals(applicationProperties.getSystem().getDisableSanitize());
|
||||
|
||||
byte[] pdfBytes =
|
||||
FileToPdf.convertHtmlToPdf(
|
||||
runtimePathConfig.getWeasyPrintPath(),
|
||||
null,
|
||||
htmlContent.getBytes(),
|
||||
"converted.html",
|
||||
disableSanitize,
|
||||
tempFileManager);
|
||||
tempFileManager,
|
||||
customHtmlSanitizer);
|
||||
pdfBytes = pdfDocumentFactory.createNewBytesBasedOnOldDocument(pdfBytes);
|
||||
String outputFilename =
|
||||
originalFilename.replaceFirst("[.][^.]+$", "")
|
||||
|
||||
+14
-1
@@ -2,6 +2,7 @@ package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@@ -26,6 +27,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import stirling.software.common.configuration.RuntimePathConfig;
|
||||
import stirling.software.common.model.api.GeneralFile;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.CustomHtmlSanitizer;
|
||||
import stirling.software.common.util.ProcessExecutor;
|
||||
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.common.util.WebResponseUtils;
|
||||
@@ -38,6 +40,7 @@ public class ConvertOfficeController {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
private final RuntimePathConfig runtimePathConfig;
|
||||
private final CustomHtmlSanitizer customHtmlSanitizer;
|
||||
|
||||
public File convertToPdf(MultipartFile inputFile) throws IOException, InterruptedException {
|
||||
// Check for valid file extension
|
||||
@@ -50,7 +53,17 @@ public class ConvertOfficeController {
|
||||
// Save the uploaded file to a temporary location
|
||||
Path tempInputFile =
|
||||
Files.createTempFile("input_", "." + FilenameUtils.getExtension(originalFilename));
|
||||
inputFile.transferTo(tempInputFile);
|
||||
|
||||
// Check if the file is HTML and apply sanitization if needed
|
||||
String fileExtension = FilenameUtils.getExtension(originalFilename).toLowerCase();
|
||||
if ("html".equals(fileExtension) || "htm".equals(fileExtension)) {
|
||||
// Read and sanitize HTML content
|
||||
String htmlContent = new String(inputFile.getBytes(), StandardCharsets.UTF_8);
|
||||
String sanitizedHtml = customHtmlSanitizer.sanitize(htmlContent);
|
||||
Files.write(tempInputFile, sanitizedHtml.getBytes(StandardCharsets.UTF_8));
|
||||
} else {
|
||||
inputFile.transferTo(tempInputFile);
|
||||
}
|
||||
|
||||
// Prepare the output file path
|
||||
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
|
||||
|
||||
Reference in New Issue
Block a user