diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0a36cc4a..44759444 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -34,107 +34,37 @@ env:
GIT_PASSWORD: ${{ secrets.BOT_GITHUB_TOKEN }}
GITHUB_ACTIONS_DEPLOY_TIMEOUT: 120
+permissions:
+ contents: read
+
jobs:
pre_commit:
runs-on: ubuntu-latest
steps:
- uses: Alfresco/alfresco-build-tools/.github/actions/pre-commit@v9.3.1
- veracode_sca:
- name: "Veracode - Source Clear Scan (SCA)"
+ test_run_check:
+ name: "Test run check"
runs-on: ubuntu-latest
- needs:
- - pre_commit
- if: >
- github.ref_name == 'master' ||
- github.event_name == 'pull_request'
+ outputs:
+ tests: ${{ steps.check.outputs.tests }}
steps:
- - uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v9.3.1
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v9.3.1
- - name: "Clean-up SNAPSHOT artifacts"
- run: find "${HOME}/.m2/repository/" -type d -name "*-SNAPSHOT*" | xargs -r -l rm -rf
- - uses: Alfresco/alfresco-build-tools/.github/actions/veracode@v9.3.1
- continue-on-error: true
- with:
- srcclr-api-token: ${{ secrets.SRCCLR_API_TOKEN }}
-
- veracode_sast:
- name: "Pipeline SAST Scan"
- runs-on: ubuntu-latest
- needs:
- - pre_commit
- if: >
- (github.ref_name == 'master' || startsWith(github.ref_name, 'SP/') || startsWith(github.ref_name, 'HF/') || github.event_name == 'pull_request') &&
- github.actor != 'dependabot[bot]' &&
- !contains(github.event.head_commit.message, '[skip tests]')
- steps:
- - uses: actions/checkout@v4
- - uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v9.3.1
- - uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v9.3.1
- - name: "Login to Docker Hub"
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.DOCKER_USERNAME }}
- password: ${{ secrets.DOCKER_PASSWORD }}
- - name: "Login to Quay.io"
- uses: docker/login-action@v3
- with:
- registry: quay.io
- username: ${{ secrets.QUAY_USERNAME }}
- password: ${{ secrets.QUAY_PASSWORD }}
- - uses: Alfresco/alfresco-build-tools/.github/actions/github-download-file@v9.3.1
- with:
- token: ${{ secrets.BOT_GITHUB_TOKEN }}
- repository: "Alfresco/veracode-baseline-archive"
- file-path: "alfresco-transform-core/alfresco-transform-core-baseline.json"
- target: "baseline.json"
- - name: "Build"
- run: mvn -B -U install -DskipTests
- - name: "Create zip"
+ - id: check
run: |
- mkdir -p to-scan
- for file in engines/aio/target/alfresco-transform-core-aio-*.jar engines/base/target/alfresco-base-t-engine-*.jar model/target/alfresco-transform-model-*.jar
- do
- if [[ $file != *javadoc.jar ]] && [[ $file != *sources.jar ]] && [[ $file != *tests.jar ]]; then
- mv "$file" to-scan/
- fi
- done
- # Removing the aspectjweaver and bouncycastle jars from the scan, since Veracode detects them as 1st party code and fails the scan. TO BE REVERTED ONCE VERACODE FIXES THE ISSUE
- zip -d to-scan/alfresco-transform*.jar "BOOT-INF/lib/bcmail-jdk18on-*.jar" "BOOT-INF/lib/bcprov-jdk18on-*.jar" "BOOT-INF/lib/aspectjweaver*.jar"
- zip -r to-scan.zip to-scan
- - name: "Run SAST Scan"
- uses: veracode/Veracode-pipeline-scan-action@v1.0.16
- with:
- vid: ${{ secrets.VERACODE_API_ID }}
- vkey: ${{ secrets.VERACODE_API_KEY }}
- file: "to-scan.zip"
- fail_build: true
- project_name: alfresco-transform-core
- issue_details: true
- veracode_policy_name: Alfresco Default
- summary_output: true
- summary_output_file: results.json
- summary_display: true
- baseline_file: baseline.json
- include: "to-scan/alfresco*"
- - name: Upload scan result
- if: success() || failure()
- run: zip readable_output.zip results.json
- - name: Upload Artifact
- if: success() || failure()
- uses: actions/upload-artifact@v4
- with:
- name: Veracode Pipeline-Scan Results (Human Readable)
- path: readable_output.zip
+ echo "tests=true" >> "$GITHUB_OUTPUT"
+ if: >
+ (
+ (github.ref_name == 'master' || startsWith(github.ref_name, 'SP/') || startsWith(github.ref_name, 'HF/') || github.event_name == 'pull_request') &&
+ !contains(github.event.head_commit.message, '[skip tests]')
+ ) ||
+ contains(github.event.head_commit.message, '[run tests]')
pmd_scan:
name: "PMD Scan"
runs-on: ubuntu-latest
- if: >
- github.event_name == 'pull_request' &&
- !contains(github.event.head_commit.message, '[skip pmd]') &&
- !contains(github.event.head_commit.message, '[skip tests]')
+ needs:
+ - test_run_check
+ if: needs.test_run_check.outputs.tests == 'true' && github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v9.3.1
@@ -148,9 +78,8 @@ jobs:
runs-on: ubuntu-latest
needs:
- pre_commit
- if: >
- github.ref_name == 'master' &&
- github.event_name != 'pull_request'
+ - test_run_check
+ if: needs.test_run_check.outputs.tests == 'true'
steps:
- uses: actions/checkout@v4
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v9.3.1
@@ -186,6 +115,8 @@ jobs:
runs-on: ubuntu-latest
needs:
- pre_commit
+ - test_run_check
+ if: needs.test_run_check.outputs.tests == 'true'
strategy:
fail-fast: false
matrix:
@@ -243,6 +174,8 @@ jobs:
runs-on: ubuntu-latest
needs:
- pre_commit
+ - test_run_check
+ if: needs.test_run_check.outputs.tests == 'true'
strategy:
fail-fast: false
matrix:
@@ -284,7 +217,7 @@ jobs:
release:
name: "Release"
runs-on: ubuntu-latest
- needs: [veracode_sca, build_and_test, all_tests_matrix, e2e_javaruntime_tests]
+ needs: [build_and_test, all_tests_matrix, e2e_javaruntime_tests]
if: >
!(failure() || cancelled()) &&
contains(github.event.head_commit.message, '[release]') &&
diff --git a/.github/workflows/dependency-graph.yml b/.github/workflows/dependency-graph.yml
index 1611a05c..7d626553 100644
--- a/.github/workflows/dependency-graph.yml
+++ b/.github/workflows/dependency-graph.yml
@@ -10,6 +10,9 @@ on:
workflow_call:
workflow_dispatch:
+permissions:
+ contents: write
+
jobs:
scan-dependencies:
runs-on: ubuntu-latest
diff --git a/.github/workflows/precommit_formatter.yml b/.github/workflows/precommit_formatter.yml
index 3205fe70..c0aecb64 100644
--- a/.github/workflows/precommit_formatter.yml
+++ b/.github/workflows/precommit_formatter.yml
@@ -5,10 +5,15 @@ on:
branches:
- precommit/**
+permissions:
+ contents: read
+
jobs:
format-code:
name: "Reformat code"
runs-on: ubuntu-latest
+ permissions:
+ contents: write
if: contains(github.event.head_commit.message, '[reformat code]')
steps:
- uses: actions/checkout@v4
diff --git a/deprecated/alfresco-transformer-base/pom.xml b/deprecated/alfresco-transformer-base/pom.xml
index bb2a075f..7d53d1a2 100644
--- a/deprecated/alfresco-transformer-base/pom.xml
+++ b/deprecated/alfresco-transformer-base/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-transform-core
- 5.4.3-A.6-SNAPSHOT
+ 5.4.4-A.12-SNAPSHOT
../../pom.xml
diff --git a/deprecated/alfresco-transformer-base/src/main/java/org/alfresco/transformer/fs/FileManager.java b/deprecated/alfresco-transformer-base/src/main/java/org/alfresco/transformer/fs/FileManager.java
index 2b4c9ed3..600e558e 100644
--- a/deprecated/alfresco-transformer-base/src/main/java/org/alfresco/transformer/fs/FileManager.java
+++ b/deprecated/alfresco-transformer-base/src/main/java/org/alfresco/transformer/fs/FileManager.java
@@ -83,12 +83,14 @@ public class FileManager
{
filename = checkFilename(false, filename);
LogEntry.setTarget(filename);
- return TempFileProvider.createTempFile("target_", "_" + filename);
+ File created = TempFileProvider.createTempFile("target_", "_" + filename);
+ return assertInsideTempDir(created);
}
public static void deleteFile(final File file) throws Exception
{
- if (!file.delete())
+ final File safeFile = assertInsideTempDir(file);
+ if (!safeFile.delete())
{
throw new Exception("Failed to delete file");
}
@@ -115,11 +117,32 @@ public class FileManager
return filename;
}
- private static void save(MultipartFile multipartFile, File file)
+ private static File assertInsideTempDir(File candidate)
{
try
{
- Files.copy(multipartFile.getInputStream(), file.toPath(),
+ File tempRoot = TempFileProvider.getTempDir();
+ String candidateCanonical = candidate.getCanonicalPath();
+ String parentCanonical = tempRoot.getCanonicalPath();
+ if (!candidateCanonical.startsWith(parentCanonical + File.separator)
+ && !candidateCanonical.equals(parentCanonical))
+ {
+ throw new TransformException(INTERNAL_SERVER_ERROR, "Resolved file escapes the temp directory");
+ }
+ return new File(candidateCanonical);
+ }
+ catch (IOException e)
+ {
+ throw new TransformException(INTERNAL_SERVER_ERROR, "Unable to resolve canonical path", e);
+ }
+ }
+
+ private static void save(MultipartFile multipartFile, File file)
+ {
+ final File safeFile = assertInsideTempDir(file);
+ try
+ {
+ Files.copy(multipartFile.getInputStream(), safeFile.toPath(),
StandardCopyOption.REPLACE_EXISTING);
}
catch (IOException e)
@@ -130,9 +153,10 @@ public class FileManager
public static void save(Resource body, File file)
{
+ final File safeFile = assertInsideTempDir(file);
try
{
- Files.copy(body.getInputStream(), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ Files.copy(body.getInputStream(), safeFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
catch (IOException e)
{
@@ -142,9 +166,10 @@ public class FileManager
private static Resource load(File file)
{
+ final File safeFile = assertInsideTempDir(file);
try
{
- Resource resource = new UrlResource(file.toURI());
+ Resource resource = new UrlResource(safeFile.toURI());
if (resource.exists() || resource.isReadable())
{
return resource;
@@ -222,7 +247,7 @@ public class FileManager
String filename = multipartFile.getOriginalFilename();
long size = multipartFile.getSize();
filename = checkFilename(true, filename);
- File file = TempFileProvider.createTempFile("source_", "_" + filename);
+ File file = assertInsideTempDir(TempFileProvider.createTempFile("source_", "_" + filename));
request.setAttribute(SOURCE_FILE, file);
save(multipartFile, file);
LogEntry.setSource(filename, size);
diff --git a/deprecated/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractMetadataExtractsIT.java b/deprecated/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractMetadataExtractsIT.java
index 2a163f89..822d80fb 100644
--- a/deprecated/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractMetadataExtractsIT.java
+++ b/deprecated/alfresco-transformer-base/src/test/java/org/alfresco/transformer/AbstractMetadataExtractsIT.java
@@ -39,6 +39,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
+import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
@@ -101,7 +102,8 @@ public abstract class AbstractMetadataExtractsIT
String metadataFilename = sourceFile + "_metadata.json";
Map actualMetadata = readMetadata(response.getBody().getInputStream());
- File actualMetadataFile = new File(metadataFilename);
+ File actualMetadataFile = Files.createTempFile(
+ "actual-" + new File(sourceFile).getName() + "-", ".json").toFile();
jsonObjectMapper.writerWithDefaultPrettyPrinter().writeValue(actualMetadataFile, actualMetadata);
Map expectedMetadata = readExpectedMetadata(metadataFilename, actualMetadataFile);
@@ -118,6 +120,10 @@ public abstract class AbstractMetadataExtractsIT
private Map readExpectedMetadata(String filename, File actualMetadataFile) throws IOException
{
+ if (filename.contains("..") || filename.contains("/") || filename.contains("\\"))
+ {
+ throw new IllegalArgumentException("Invalid expected metadata filename: " + filename);
+ }
try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filename))
{
if (inputStream == null)
diff --git a/engines/aio/Dockerfile b/engines/aio/Dockerfile
index 4abd3761..5ede5887 100644
--- a/engines/aio/Dockerfile
+++ b/engines/aio/Dockerfile
@@ -21,7 +21,7 @@ ARG LIBREOFFICE_VERSION=7.2.5
ENV LIBREOFFICE_RPM_URL=https://nexus.alfresco.com/nexus/service/local/repositories/thirdparty/org/libreoffice/libreoffice-dist/${LIBREOFFICE_VERSION}/libreoffice-dist-${LIBREOFFICE_VERSION}-linux.gz
ENV LIBREOFFICE_ARM64_RPM_URL=https://dl.rockylinux.org/pub/rocky/9/devel/aarch64/os/Packages/l/
ENV LIBREOFFICE_ARM64_RPM_VERSION=libreoffice-7.1.8.1
-ARG PDF_RENDERER_VERSION=1.3.0-76
+ARG PDF_RENDERER_VERSION=1.3.0-78
ENV ALFRESCO_PDF_RENDERER_LIB_RPM_URL=https://nexus.alfresco.com/nexus/service/local/repositories/releases/org/alfresco/alfresco-pdf-renderer/${PDF_RENDERER_VERSION}/alfresco-pdf-renderer-${PDF_RENDERER_VERSION}-linux.tgz
ENV ALFRESCO_PDF_RENDERER_ARM64_LIB_RPM_URL=https://nexus.alfresco.com/nexus/service/local/repositories/releases/org/alfresco/alfresco-pdf-renderer/${PDF_RENDERER_VERSION}/alfresco-pdf-renderer-${PDF_RENDERER_VERSION}-linux-arm.tgz
diff --git a/engines/aio/pom.xml b/engines/aio/pom.xml
index f178a097..5213d254 100644
--- a/engines/aio/pom.xml
+++ b/engines/aio/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-transform-core
- 5.4.3-A.6-SNAPSHOT
+ 5.4.4-A.12-SNAPSHOT
../../pom.xml
diff --git a/engines/base/pom.xml b/engines/base/pom.xml
index 9a58b9e9..b4b7ebeb 100644
--- a/engines/base/pom.xml
+++ b/engines/base/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-transform-core
- 5.4.3-A.6-SNAPSHOT
+ 5.4.4-A.12-SNAPSHOT
../../pom.xml
diff --git a/engines/base/src/main/java/org/alfresco/transform/base/executors/AbstractCommandExecutor.java b/engines/base/src/main/java/org/alfresco/transform/base/executors/AbstractCommandExecutor.java
index 93053dd1..7537a64f 100644
--- a/engines/base/src/main/java/org/alfresco/transform/base/executors/AbstractCommandExecutor.java
+++ b/engines/base/src/main/java/org/alfresco/transform/base/executors/AbstractCommandExecutor.java
@@ -30,6 +30,7 @@ import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.alfresco.transform.base.executors.RuntimeExec.ExecutionResult;
+import static org.alfresco.transform.base.fs.FileManager.assertWithinTempDir;
import java.io.File;
import java.util.Map;
@@ -48,6 +49,7 @@ public abstract class AbstractCommandExecutor implements CommandExecutor
@Override
public void run(Map properties, File targetFile, Long timeout)
{
+ targetFile = assertWithinTempDir(targetFile);
timeout = timeout != null && timeout > 0 ? timeout : 0;
final ExecutionResult result = transformCommand.execute(properties, timeout);
diff --git a/engines/base/src/main/java/org/alfresco/transform/base/executors/RuntimeExec.java b/engines/base/src/main/java/org/alfresco/transform/base/executors/RuntimeExec.java
index 672ba677..3bb4e404 100644
--- a/engines/base/src/main/java/org/alfresco/transform/base/executors/RuntimeExec.java
+++ b/engines/base/src/main/java/org/alfresco/transform/base/executors/RuntimeExec.java
@@ -666,12 +666,8 @@ public class RuntimeExec
for (Map.Entry entry : execProperties.entrySet())
{
String key = entry.getKey();
- String value = entry.getValue();
- // ignore null
- if (value == null)
- {
- value = "";
- }
+ String value = entry.getValue() == null ? "" : entry.getValue();
+ validateCommandPropertyValue(key, value);
// progressively replace the property in the command
key = (VAR_OPEN + key + VAR_CLOSE);
int index = sb.indexOf(key);
@@ -704,6 +700,55 @@ public class RuntimeExec
return adjustedCommandElements.toArray(new String[0]);
}
+ private void validateCommandPropertyValue(String key, String value)
+ {
+ if (value.contains("\n") || value.contains("\r") || value.contains("\0"))
+ {
+ throw new IllegalArgumentException(
+ "Command property '" + key + "' contains an illegal character");
+ }
+
+ if ("source".equals(key) || "target".equals(key))
+ {
+ validatePathProperty(key, value);
+ }
+ else if ("sourceMimetype".equals(key) || "targetMimetype".equals(key))
+ {
+ validateMimetypeProperty(key, value);
+ }
+ }
+
+ private void validatePathProperty(String key, String value)
+ {
+ if (value.isBlank())
+ {
+ throw new IllegalArgumentException("Command property '" + key + "' must not be blank");
+ }
+
+ // Allow quotes/backticks in paths; this class executes via Runtime.exec(String[]) (no shell parsing)
+
+ File file = new File(value);
+ if (!file.isAbsolute())
+ {
+ throw new IllegalArgumentException(
+ "Command property '" + key + "' must be an absolute path");
+ }
+ }
+
+ private void validateMimetypeProperty(String key, String value)
+ {
+ if (value.isBlank())
+ {
+ throw new IllegalArgumentException("Command property '" + key + "' must not be blank");
+ }
+
+ if (!value.matches("^[a-zA-Z0-9!#$&^_.+-]+/[a-zA-Z0-9!#$&^_.+-]+$"))
+ {
+ throw new IllegalArgumentException(
+ "Command property '" + key + "' is not a valid mimetype");
+ }
+ }
+
/**
* Object to carry the results of an execution to the caller.
*
diff --git a/engines/base/src/main/java/org/alfresco/transform/base/fs/FileManager.java b/engines/base/src/main/java/org/alfresco/transform/base/fs/FileManager.java
index f1575bea..1d576500 100644
--- a/engines/base/src/main/java/org/alfresco/transform/base/fs/FileManager.java
+++ b/engines/base/src/main/java/org/alfresco/transform/base/fs/FileManager.java
@@ -57,6 +57,7 @@ import org.alfresco.transform.base.logging.LogEntry;
import org.alfresco.transform.common.ExtensionService;
import org.alfresco.transform.exceptions.TransformException;
+@SuppressWarnings("PMD.GodClass")
public class FileManager
{
public static final String SOURCE_FILE = "sourceFile";
@@ -65,6 +66,34 @@ public class FileManager
private FileManager()
{}
+ static File assertContained(File candidate, File parent)
+ {
+ try
+ {
+ String candidateCanonical = candidate.getCanonicalPath();
+ String parentCanonical = parent.getCanonicalPath();
+ if (!candidateCanonical.equals(parentCanonical)
+ && !candidateCanonical.startsWith(parentCanonical + File.separator))
+ {
+ throw new TransformException(BAD_REQUEST, "The resolved path escapes the temp directory");
+ }
+ return new File(candidateCanonical);
+ }
+ catch (IOException e)
+ {
+ throw new TransformException(BAD_REQUEST, "Unable to resolve canonical path", e);
+ }
+ }
+
+ public static File assertWithinTempDir(File file)
+ {
+ if (file == null)
+ {
+ return null;
+ }
+ return assertContained(file, new File(System.getProperty("java.io.tmpdir")));
+ }
+
public static File createSourceFile(HttpServletRequest request, InputStream inputStream, String sourceMimetype, String sourceFileName)
{
try
@@ -74,14 +103,15 @@ public class FileManager
? TempFileProvider.createTempFile("source_", extension)
: TempFileProvider.createFileWithinUUIDTempDir(sourceFileName);
- Files.copy(inputStream, file.toPath(), REPLACE_EXISTING);
+ File safeFile = assertContained(file, file.getParentFile());
+ Files.copy(inputStream, safeFile.toPath(), REPLACE_EXISTING);
if (request != null)
{
- request.setAttribute(SOURCE_FILE, file);
+ request.setAttribute(SOURCE_FILE, safeFile);
}
- LogEntry.setSource(file.getName(), file.length());
- return file;
+ LogEntry.setSource(safeFile.getName(), safeFile.length());
+ return safeFile;
}
catch (Exception e)
{
@@ -94,7 +124,8 @@ public class FileManager
try
{
String extension = "." + ExtensionService.getExtensionForTargetMimetype(targetMimetype, sourceMimetype);
- File file = TempFileProvider.createTempFile("target_", extension);
+ File raw = TempFileProvider.createTempFile("target_", extension);
+ File file = assertContained(raw, raw.getParentFile());
if (request != null)
{
request.setAttribute(TARGET_FILE, file);
diff --git a/engines/base/src/main/java/org/alfresco/transform/base/transform/TransformHandler.java b/engines/base/src/main/java/org/alfresco/transform/base/transform/TransformHandler.java
index 9cbcce82..6165e726 100644
--- a/engines/base/src/main/java/org/alfresco/transform/base/transform/TransformHandler.java
+++ b/engines/base/src/main/java/org/alfresco/transform/base/transform/TransformHandler.java
@@ -32,6 +32,7 @@ import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
+import static org.alfresco.transform.base.fs.FileManager.assertWithinTempDir;
import static org.alfresco.transform.base.fs.FileManager.createAttachment;
import static org.alfresco.transform.base.fs.FileManager.createTargetFile;
import static org.alfresco.transform.base.fs.FileManager.getDirectAccessUrlInputStream;
@@ -378,6 +379,7 @@ public class TransformHandler
private OutputStream getOutputStreamFromFile(File targetFile) throws IOException
{
+ targetFile = assertWithinTempDir(targetFile);
return new BufferedOutputStream(new FileOutputStream(targetFile));
}
diff --git a/engines/base/src/test/java/org/alfresco/transform/base/metadata/AbstractMetadataExtractsIT.java b/engines/base/src/test/java/org/alfresco/transform/base/metadata/AbstractMetadataExtractsIT.java
index bd657081..a5b2641d 100644
--- a/engines/base/src/test/java/org/alfresco/transform/base/metadata/AbstractMetadataExtractsIT.java
+++ b/engines/base/src/test/java/org/alfresco/transform/base/metadata/AbstractMetadataExtractsIT.java
@@ -39,6 +39,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
+import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
@@ -100,7 +101,8 @@ public abstract class AbstractMetadataExtractsIT
String metadataFilename = sourceFile + "_metadata.json";
Map actualMetadata = readMetadata(response.getBody().getInputStream());
- File actualMetadataFile = new File(metadataFilename);
+ File actualMetadataFile = Files.createTempFile(
+ "actual-" + new File(sourceFile).getName() + "-", ".json").toFile();
jsonObjectMapper.writerWithDefaultPrettyPrinter().writeValue(actualMetadataFile, actualMetadata);
Map expectedMetadata = readExpectedMetadata(metadataFilename, actualMetadataFile);
@@ -117,6 +119,10 @@ public abstract class AbstractMetadataExtractsIT
private Map readExpectedMetadata(String filename, File actualMetadataFile) throws IOException
{
+ if (filename.contains("..") || filename.contains("/") || filename.contains("\\"))
+ {
+ throw new IllegalArgumentException("Invalid expected metadata filename: " + filename);
+ }
try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filename))
{
if (inputStream == null)
diff --git a/engines/example/pom.xml b/engines/example/pom.xml
index 381b6004..07a1f6fe 100644
--- a/engines/example/pom.xml
+++ b/engines/example/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-transform-core
- 5.4.3-A.6-SNAPSHOT
+ 5.4.4-A.12-SNAPSHOT
../../pom.xml
diff --git a/engines/imagemagick/pom.xml b/engines/imagemagick/pom.xml
index d4736517..61cd647d 100644
--- a/engines/imagemagick/pom.xml
+++ b/engines/imagemagick/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-transform-core
- 5.4.3-A.6-SNAPSHOT
+ 5.4.4-A.12-SNAPSHOT
../../pom.xml
diff --git a/engines/libreoffice/pom.xml b/engines/libreoffice/pom.xml
index 6d179ff1..da517312 100644
--- a/engines/libreoffice/pom.xml
+++ b/engines/libreoffice/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-transform-core
- 5.4.3-A.6-SNAPSHOT
+ 5.4.4-A.12-SNAPSHOT
../../pom.xml
diff --git a/engines/libreoffice/src/main/java/org/alfresco/transform/libreoffice/transformers/LibreOfficeTransformer.java b/engines/libreoffice/src/main/java/org/alfresco/transform/libreoffice/transformers/LibreOfficeTransformer.java
index 700fa9de..e15062fb 100644
--- a/engines/libreoffice/src/main/java/org/alfresco/transform/libreoffice/transformers/LibreOfficeTransformer.java
+++ b/engines/libreoffice/src/main/java/org/alfresco/transform/libreoffice/transformers/LibreOfficeTransformer.java
@@ -29,6 +29,8 @@ package org.alfresco.transform.libreoffice.transformers;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
+import static org.alfresco.transform.base.fs.FileManager.assertWithinTempDir;
+
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
@@ -137,6 +139,8 @@ public class LibreOfficeTransformer implements JavaExecutor, CustomTransformerFi
public void transform(String sourceMimetype, String targetMimetype, Map transformOptions,
File sourceFile, File targetFile, TransformManager transformManager)
{
+ sourceFile = assertWithinTempDir(sourceFile);
+ targetFile = assertWithinTempDir(targetFile);
call(sourceFile, targetFile);
}
diff --git a/engines/misc/pom.xml b/engines/misc/pom.xml
index 0e3dd6f6..76a61ca8 100644
--- a/engines/misc/pom.xml
+++ b/engines/misc/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-transform-core
- 5.4.3-A.6-SNAPSHOT
+ 5.4.4-A.12-SNAPSHOT
../../pom.xml
diff --git a/engines/misc/src/main/java/org/alfresco/transform/misc/metadataExtractors/HtmlMetadataExtractor.java b/engines/misc/src/main/java/org/alfresco/transform/misc/metadataExtractors/HtmlMetadataExtractor.java
index 8f460c9a..dc6a880a 100644
--- a/engines/misc/src/main/java/org/alfresco/transform/misc/metadataExtractors/HtmlMetadataExtractor.java
+++ b/engines/misc/src/main/java/org/alfresco/transform/misc/metadataExtractors/HtmlMetadataExtractor.java
@@ -26,6 +26,7 @@
*/
package org.alfresco.transform.misc.metadataExtractors;
+import static org.alfresco.transform.base.fs.FileManager.assertWithinTempDir;
import static org.alfresco.transform.base.metadata.AbstractMetadataExtractorEmbedder.Type.EXTRACTOR;
import java.io.File;
@@ -104,7 +105,7 @@ public class HtmlMetadataExtractor extends AbstractMetadataExtractorEmbedder
// This Extractor retries if the encoding needs to be changed, so we need to reread the source,
// so cannot use the input stream provided, as it will get closed.
- final File sourceFile = transformManager.createSourceFile();
+ final File sourceFile = assertWithinTempDir(transformManager.createSourceFile());
HTMLEditorKit.ParserCallback callback = new HTMLEditorKit.ParserCallback() {
StringBuffer title = null;
diff --git a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/AppleIWorksContentTransformer.java b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/AppleIWorksContentTransformer.java
index b0233e83..b00428cc 100644
--- a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/AppleIWorksContentTransformer.java
+++ b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/AppleIWorksContentTransformer.java
@@ -26,6 +26,7 @@
*/
package org.alfresco.transform.misc.transformers;
+import static org.alfresco.transform.base.fs.FileManager.assertWithinTempDir;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_IMAGE_JPEG;
import java.io.BufferedInputStream;
@@ -83,6 +84,8 @@ public class AppleIWorksContentTransformer implements CustomTransformerFileAdapt
public void transform(String sourceMimetype, String targetMimetype, Map transformOptions,
File sourceFile, File targetFile, TransformManager transformManager)
{
+ sourceFile = assertWithinTempDir(sourceFile);
+ targetFile = assertWithinTempDir(targetFile);
logger.debug("Performing IWorks to jpeg transform with sourceMimetype={} targetMimetype={}",
sourceMimetype, targetMimetype);
diff --git a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/EMLTransformer.java b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/EMLTransformer.java
index 794198da..090ceaea 100644
--- a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/EMLTransformer.java
+++ b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/EMLTransformer.java
@@ -26,6 +26,7 @@
*/
package org.alfresco.transform.misc.transformers;
+import static org.alfresco.transform.base.fs.FileManager.assertWithinTempDir;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_HTML;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_MULTIPART_ALTERNATIVE;
import static org.alfresco.transform.common.Mimetype.MIMETYPE_TEXT_PLAIN;
@@ -81,6 +82,8 @@ public class EMLTransformer implements CustomTransformerFileAdaptor
public void transform(String sourceMimetype, String targetMimetype, Map transformOptions,
File sourceFile, File targetFile, TransformManager transformManager) throws Exception
{
+ sourceFile = assertWithinTempDir(sourceFile);
+ targetFile = assertWithinTempDir(targetFile);
logger.debug("Performing RFC822 to text transform.");
// Use try with resource
try (InputStream contentInputStream = new BufferedInputStream(
diff --git a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/HtmlParserContentTransformer.java b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/HtmlParserContentTransformer.java
index e49b9255..c2549aad 100644
--- a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/HtmlParserContentTransformer.java
+++ b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/HtmlParserContentTransformer.java
@@ -26,6 +26,7 @@
*/
package org.alfresco.transform.misc.transformers;
+import static org.alfresco.transform.base.fs.FileManager.assertWithinTempDir;
import static org.alfresco.transform.common.RequestParamMap.HTML_COLLAPSE;
import static org.alfresco.transform.common.RequestParamMap.SOURCE_ENCODING;
@@ -89,8 +90,10 @@ public class HtmlParserContentTransformer implements CustomTransformerFileAdapto
@Override
public void transform(final String sourceMimetype, final String targetMimetype,
final Map transformOptions,
- final File sourceFile, final File targetFile, TransformManager transformManager) throws Exception
+ File sourceFile, File targetFile, TransformManager transformManager) throws Exception
{
+ sourceFile = assertWithinTempDir(sourceFile);
+ targetFile = assertWithinTempDir(targetFile);
String sourceEncoding = transformOptions.get(SOURCE_ENCODING);
checkEncodingParameter(sourceEncoding, SOURCE_ENCODING);
boolean collapse;
diff --git a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/OOXMLThumbnailContentTransformer.java b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/OOXMLThumbnailContentTransformer.java
index 5620a214..0e5b26f9 100644
--- a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/OOXMLThumbnailContentTransformer.java
+++ b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/OOXMLThumbnailContentTransformer.java
@@ -26,6 +26,8 @@
*/
package org.alfresco.transform.misc.transformers;
+import static org.alfresco.transform.base.fs.FileManager.assertWithinTempDir;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -68,8 +70,10 @@ public class OOXMLThumbnailContentTransformer implements CustomTransformerFileAd
@Override
public void transform(final String sourceMimetype, final String targetMimetype, final Map parameters,
- final File sourceFile, final File targetFile, TransformManager transformManager) throws Exception
+ File sourceFile, File targetFile, TransformManager transformManager) throws Exception
{
+ sourceFile = assertWithinTempDir(sourceFile);
+ targetFile = assertWithinTempDir(targetFile);
if (logger.isDebugEnabled())
{
logger.debug("Performing OOXML to jpeg transform with sourceMimetype=" + sourceMimetype
diff --git a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/StringExtractingContentTransformer.java b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/StringExtractingContentTransformer.java
index 0355ef9c..43e3e600 100644
--- a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/StringExtractingContentTransformer.java
+++ b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/StringExtractingContentTransformer.java
@@ -26,6 +26,7 @@
*/
package org.alfresco.transform.misc.transformers;
+import static org.alfresco.transform.base.fs.FileManager.assertWithinTempDir;
import static org.alfresco.transform.common.RequestParamMap.SOURCE_ENCODING;
import static org.alfresco.transform.common.RequestParamMap.TARGET_ENCODING;
@@ -79,8 +80,10 @@ public class StringExtractingContentTransformer implements CustomTransformerFile
*/
@Override
public void transform(final String sourceMimetype, final String targetMimetype, final Map transformOptions,
- final File sourceFile, final File targetFile, TransformManager transformManager) throws Exception
+ File sourceFile, File targetFile, TransformManager transformManager) throws Exception
{
+ sourceFile = assertWithinTempDir(sourceFile);
+ targetFile = assertWithinTempDir(targetFile);
String sourceEncoding = transformOptions.get(SOURCE_ENCODING);
String targetEncoding = transformOptions.get(TARGET_ENCODING);
diff --git a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/TextToPdfContentTransformer.java b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/TextToPdfContentTransformer.java
index 4f203f0a..54cdadaa 100644
--- a/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/TextToPdfContentTransformer.java
+++ b/engines/misc/src/main/java/org/alfresco/transform/misc/transformers/TextToPdfContentTransformer.java
@@ -26,6 +26,7 @@
*/
package org.alfresco.transform.misc.transformers;
+import static org.alfresco.transform.base.fs.FileManager.assertWithinTempDir;
import static org.alfresco.transform.common.RequestParamMap.PAGE_LIMIT;
import static org.alfresco.transform.common.RequestParamMap.PDF_FONT;
import static org.alfresco.transform.common.RequestParamMap.PDF_FONT_SIZE;
@@ -149,8 +150,10 @@ public class TextToPdfContentTransformer implements CustomTransformerFileAdaptor
@Override
public void transform(final String sourceMimetype, final String targetMimetype, final Map transformOptions,
- final File sourceFile, final File targetFile, TransformManager transformManager) throws Exception
+ File sourceFile, File targetFile, TransformManager transformManager) throws Exception
{
+ sourceFile = assertWithinTempDir(sourceFile);
+ targetFile = assertWithinTempDir(targetFile);
String sourceEncoding = transformOptions.get(SOURCE_ENCODING);
String stringPageLimit = transformOptions.get(PAGE_LIMIT);
int pageLimit = -1;
diff --git a/engines/pdfrenderer/Dockerfile b/engines/pdfrenderer/Dockerfile
index 7030c8f0..42804f3b 100644
--- a/engines/pdfrenderer/Dockerfile
+++ b/engines/pdfrenderer/Dockerfile
@@ -6,7 +6,7 @@
ARG JAVA_BASE_IMAGE=alfresco/alfresco-base-java:jre17-rockylinux9@sha256:f98833508b7be8c4b44a25450f9faac44cacfdc075f2295e02836b93fd05bb9c
FROM ${JAVA_BASE_IMAGE}
-ARG PDF_RENDERER_VERSION=1.3.0-76
+ARG PDF_RENDERER_VERSION=1.3.0-78
ENV ALFRESCO_PDF_RENDERER_LIB_RPM_URL=https://nexus.alfresco.com/nexus/service/local/repositories/releases/org/alfresco/alfresco-pdf-renderer/${PDF_RENDERER_VERSION}/alfresco-pdf-renderer-${PDF_RENDERER_VERSION}-linux.tgz
ENV ALFRESCO_PDF_RENDERER_ARM64_LIB_RPM_URL=https://nexus.alfresco.com/nexus/service/local/repositories/releases/org/alfresco/alfresco-pdf-renderer/${PDF_RENDERER_VERSION}/alfresco-pdf-renderer-${PDF_RENDERER_VERSION}-linux-arm.tgz
ENV JAVA_OPTS=""
diff --git a/engines/pdfrenderer/pom.xml b/engines/pdfrenderer/pom.xml
index c5cf2680..10cd41f9 100644
--- a/engines/pdfrenderer/pom.xml
+++ b/engines/pdfrenderer/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-transform-core
- 5.4.3-A.6-SNAPSHOT
+ 5.4.4-A.12-SNAPSHOT
../../pom.xml
diff --git a/engines/tika/pom.xml b/engines/tika/pom.xml
index 23a50325..55b884de 100644
--- a/engines/tika/pom.xml
+++ b/engines/tika/pom.xml
@@ -7,7 +7,7 @@
org.alfresco
alfresco-transform-core
- 5.4.3-A.6-SNAPSHOT
+ 5.4.4-A.12-SNAPSHOT
../../pom.xml
diff --git a/model/pom.xml b/model/pom.xml
index 0bce4893..73a616da 100644
--- a/model/pom.xml
+++ b/model/pom.xml
@@ -8,7 +8,7 @@
org.alfresco
alfresco-transform-core
- 5.4.3-A.6-SNAPSHOT
+ 5.4.4-A.12-SNAPSHOT
diff --git a/pom.xml b/pom.xml
index 4bdd43d4..9bd4b905 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,14 +3,14 @@
4.0.0
org.alfresco
alfresco-transform-core
- 5.4.3-A.6-SNAPSHOT
+ 5.4.4-A.12-SNAPSHOT
Alfresco Transform Core
pom
org.springframework.boot
spring-boot-starter-parent
- 4.0.6
+ 4.0.7
@@ -24,10 +24,17 @@
3.0.5
3.0.1.20
${project.version}
+<<<<<<< HEAD
2.21.2
2.21
3.1.1
3.3.1
+=======
+ 2.22.0
+ 2.22
+ 3.2.0
+ 3.2.3
+>>>>>>> origin/master
5.4.1
1.84
2.20.0
@@ -218,12 +225,17 @@
commons-codec
1.17.2
-
+
org.bouncycastle
bcprov-jdk18on
${dependency.bcprov.version}
+
+ org.bouncycastle
+ bcpkix-jdk18on
+ ${dependency.bcprov.version}
+
org.apache.tomcat.embed
tomcat-embed-core
@@ -339,6 +351,27 @@
https://raw.githubusercontent.com/Alfresco/third-party-license-overrides/master/includedLicenses.txt
https://raw.githubusercontent.com/Alfresco/third-party-license-overrides/master/licenseMerges.txt
https://raw.githubusercontent.com/Alfresco/third-party-license-overrides/master/override-THIRD-PARTY.properties
+
+
+
+ https?://www\.gnu\.org/licenses/old-licenses/lgpl-2\.1\.html
+ https://raw.githubusercontent.com/spdx/license-list-data/main/text/LGPL-2.1-only.txt
+
+
+ https?://www\.gnu\.org/software/classpath/license\.html
+ https://raw.githubusercontent.com/openjdk/jdk/d3f2498ed72089301a49ddf0bc7bd2df54368033/LICENSE
+
+
+ https?://www\.gnu\.org/licenses/lgpl\.txt
+ https://raw.githubusercontent.com/spdx/license-list-data/main/text/LGPL-3.0-only.txt
+
+
+ https?://www\.gnu\.org/licenses/gpl\.txt
+ https://raw.githubusercontent.com/spdx/license-list-data/main/text/GPL-3.0-only.txt
+
+
diff --git a/srcclr.yml b/srcclr.yml
deleted file mode 100644
index cd68c5bb..00000000
--- a/srcclr.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-# To avoid the provided dependencies we set the scope to runtime. See: https://docs.veracode.com/r/c_sc_scan_directives
-# runtime: to restrict the scan to compile and runtime dependencies.
-scope: runtime
\ No newline at end of file