diff --git a/src/strass/Dockerfile b/src/strass/Dockerfile
index 037e32b20887cf32b066c0bf7ae4158affa27f19..1e3e0528bfe190518f7b401ee69d76efc110c59c 100644
--- a/src/strass/Dockerfile
+++ b/src/strass/Dockerfile
@@ -37,6 +37,7 @@ RUN addgroup --gid 1000 kiwi \
gcc \
g++ \
libmagic1 \
+ ghostscript \
&& rm -rf /var/lib/apt/lists/* \
&& python -m pip install --upgrade pip \
&& pip install csscompressor gunicorn
diff --git a/src/strass/strass_app/tests/test_sanitize_pdf.py b/src/strass/strass_app/tests/test_sanitize_pdf.py
index 6e94032dc93d83943111893d90773c7e83084fea..e55e4bba4bda0ae82de5207d81818f9f0ae81f69 100644
--- a/src/strass/strass_app/tests/test_sanitize_pdf.py
+++ b/src/strass/strass_app/tests/test_sanitize_pdf.py
@@ -42,6 +42,20 @@ class SafePDFTestCase(TooledTestCase):
my_io = utils.safe_pdf(cv)
self.check_no_js(my_io)
+ def test_pdf_file_cleanup_with_js(self):
+ cv = open(os.path.join(self.test_data, "cv-with-js.pdf"), "rb")
+ self.assertIn('ICanSubmitTheContentOfThisFileAnywhere', str(cv.read()))
+ cv.seek(0)
+ my_io = utils._pdf_file_cleanup(cv)
+ self.check_no_js(my_io)
+
+ def test_pdf_ps_pdf_with_js(self):
+ cv = open(os.path.join(self.test_data, "cv-with-js.pdf"), "rb")
+ self.assertIn('ICanSubmitTheContentOfThisFileAnywhere', str(cv.read()))
+ cv.seek(0)
+ my_io = utils._pdf_ps_pdf(cv)
+ self.check_no_js(my_io)
+
def test_binary_file_indirect_object_iter(self):
writer = PdfWriter()
writer.add_attachment("test.txt", b"content")
diff --git a/src/strass/strass_app/utils.py b/src/strass/strass_app/utils.py
index f5d7f9c8893ff7e4e13e6587527e1531c4cbf14d..4acc450c5831e02b2a77a9646e21328a0ffa9a8e 100644
--- a/src/strass/strass_app/utils.py
+++ b/src/strass/strass_app/utils.py
@@ -18,6 +18,7 @@
import functools
import logging
+import subprocess
from abc import abstractmethod
from io import BytesIO
from typing import IO, Any
@@ -300,7 +301,10 @@ def _pdf_object_cleanup(pdf_file, obj):
del obj[k]
-def safe_pdf(my_stream: IO[Any]):
+def _pdf_file_cleanup(my_stream: IO[Any]):
+ """
+ Strip out Javascript code from the pdf file
+ """
writer = PdfWriter(clone_from=my_stream)
_pdf_object_cleanup(writer, writer.root_object.get('/Names', {}))
@@ -312,6 +316,36 @@ def safe_pdf(my_stream: IO[Any]):
return myio
+def _pdf_ps_pdf(my_stream: IO[Any]):
+ """
+ Convert file to posts script and then back to pdf to purge code and dynamic content
+ """
+ pdf2ps = subprocess.Popen(
+ ('pdf2ps', '-dLanguageLevel=1', '-', '-'),
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ )
+ cv_ps = pdf2ps.communicate(input=my_stream.read())[0]
+ pdf2ps.wait()
+
+ ps2pdf = subprocess.Popen(
+ ('ps2pdf', '-', '-'),
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ )
+ cv_safe = ps2pdf.communicate(input=cv_ps)[0]
+ ps2pdf.wait()
+
+ myio = BytesIO(cv_safe)
+ return myio
+
+
+def safe_pdf(my_stream: IO[Any]):
+ my_stream = _pdf_file_cleanup(my_stream)
+ my_stream = _pdf_ps_pdf(my_stream)
+ return my_stream
+
+
def use_markdown_or_plain_text_message() -> str:
if live_settings.markdown_enabled__bool:
return _('You can use markdown here.')
diff --git a/src/strass/test_data/README.md b/src/strass/test_data/README.md
index 5204054da0ad4564071ef40ecd426da809c2a3f2..5a24bdc487f22b53d303acf7139740a5b4985cb8 100644
--- a/src/strass/test_data/README.md
+++ b/src/strass/test_data/README.md
@@ -10,6 +10,4 @@ writer = PdfWriter(clone_from="cv.pdf")
writer.add_js('app.alert("ICanSubmitTheContentOfThisFileAnywhere.");')
with open("cv-with-js.pdf", "wb") as fp:
writer.write(fp)
-
-writer = PdfWriter(clone_from="cv-with-js.pdf")
```
\ No newline at end of file