diff --git a/requirements.txt b/requirements.txt
index 90ee39b71b..8b92504e32 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,6 +8,7 @@ colorama>=0.4.3
cryptography==38.0.3
dask==2022.9.2
deepdiff==6.3.0
+defusedxml==0.7.1
expandvars==0.9.0
fastapi[all]==0.89.1
fastapi-caching[redis]==0.3.0
diff --git a/src/fides/api/service/connectors/saas/connector_registry_service.py b/src/fides/api/service/connectors/saas/connector_registry_service.py
index aab226ada2..fe37d50ad1 100644
--- a/src/fides/api/service/connectors/saas/connector_registry_service.py
+++ b/src/fides/api/service/connectors/saas/connector_registry_service.py
@@ -40,7 +40,7 @@
replace_dataset_placeholders,
replace_version,
)
-from fides.api.util.unsafe_file_util import verify_zip
+from fides.api.util.unsafe_file_util import verify_svg, verify_zip
from fides.config import CONFIG
@@ -214,6 +214,7 @@ def save_template(cls, db: Session, zip_file: ZipFile) -> None:
)
elif info.filename.endswith(".svg"):
if not icon_contents:
+ verify_svg(file_contents)
icon_contents = str_to_b64_str(file_contents)
else:
raise ValidationError(
diff --git a/src/fides/api/util/unsafe_file_util.py b/src/fides/api/util/unsafe_file_util.py
index d8ef9bc627..5c5d99a409 100644
--- a/src/fides/api/util/unsafe_file_util.py
+++ b/src/fides/api/util/unsafe_file_util.py
@@ -1,10 +1,34 @@
from typing import Optional
from zipfile import ZipFile
+from defusedxml.ElementTree import fromstring
+
+from fides.api.common_exceptions import ValidationError
+
MAX_FILE_SIZE = 16 * 1024 * 1024 # 16 MB
CHUNK_SIZE = 1024
+def verify_svg(contents: str) -> None:
+ """
+ Verifies the provided SVG content.
+
+ This function checks the given SVG content string for potential issues and throws an exception if any are found.
+ It first attempts to parse the SVG content using 'defusedxml.fromstring'. If the parsing is unsuccessful, this
+ will raise an exception, indicating that the SVG content may contain unsafe XML.
+
+ :param contents: The SVG content as a string.
+ :raises ValidationError: If the SVG content contains unsafe XML or 'use xlink'
+ """
+ try:
+ fromstring(contents)
+ except Exception:
+ raise ValidationError("SVG file contains unsafe XML.")
+
+ if "use xlink" in contents:
+ raise ValidationError("SVG files with xlink references are not allowed.")
+
+
def verify_zip(zip_file: ZipFile, max_file_size: Optional[int] = None) -> None:
"""
Function to safely verify the contents of zipped files. It prevents potential
diff --git a/tests/ops/util/test_unsafe_file_util.py b/tests/ops/util/test_unsafe_file_util.py
index d452bcf23c..3cadda9b07 100644
--- a/tests/ops/util/test_unsafe_file_util.py
+++ b/tests/ops/util/test_unsafe_file_util.py
@@ -3,10 +3,57 @@
import pytest
-from fides.api.util.unsafe_file_util import verify_zip
+from fides.api.common_exceptions import ValidationError
+from fides.api.util.unsafe_file_util import verify_svg, verify_zip
from tests.ops.test_helpers.saas_test_utils import create_zip_file
+class TestVerifySvg:
+ def test_verify_svg(self):
+ verify_svg(
+ """
+ """
+ )
+
+ def test_verify_svg_no_laughing_allowed(self):
+ """Test "billion laughs attack" is prevented"""
+ with pytest.raises(ValidationError) as exc:
+ verify_svg(
+ """
+
+
+
+
+
+
+
+
+
+
+
+ ]>
+
+ """
+ )
+ assert "SVG file contains unsafe XML." in str(exc.value)
+
+ def test_verify_svg_with_xlink(self):
+ with pytest.raises(ValidationError) as exc:
+ verify_svg(
+ """
+ """
+ )
+ assert "SVG files with xlink references are not allowed." in str(exc.value)
+
+
class TestVerifyZip:
@pytest.fixture
def zip_file(self) -> BytesIO: