Skip to content

Commit d5bd6ad

Browse files
authored
Support for whitelisted file extensions (#12891)
* Support for whitelisted file extensions * Centralize logic
1 parent 3dab9ad commit d5bd6ad

3 files changed

Lines changed: 31 additions & 9 deletions

File tree

dojo/api_v2/serializers.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@
124124
)
125125
from dojo.user.utils import get_configuration_permissions_codenames
126126
from dojo.utils import is_scan_file_too_large
127-
from dojo.validators import tag_validator
127+
from dojo.validators import ImporterFileExtensionValidator, tag_validator
128128

129129
logger = logging.getLogger(__name__)
130130
deduplicationLogger = logging.getLogger("dojo.specific-loggers.deduplication")
@@ -2090,7 +2090,11 @@ class CommonImportScanSerializer(serializers.Serializer):
20902090
default=None,
20912091
help_text="Enter the ID of an Endpoint that is associated with the target Product. New Findings will be added to that Endpoint.",
20922092
)
2093-
file = serializers.FileField(allow_empty_file=True, required=False)
2093+
file = serializers.FileField(
2094+
allow_empty_file=True,
2095+
required=False,
2096+
validators=[ImporterFileExtensionValidator()],
2097+
)
20942098
product_type_name = serializers.CharField(required=False)
20952099
product_name = serializers.CharField(required=False)
20962100
engagement_name = serializers.CharField(required=False)

dojo/forms.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
is_finding_groups_enabled,
113113
is_scan_file_too_large,
114114
)
115-
from dojo.validators import tag_validator
115+
from dojo.validators import ImporterFileExtensionValidator, tag_validator
116116
from dojo.widgets import TableCheckboxWidget
117117

118118
logger = logging.getLogger(__name__)
@@ -525,11 +525,15 @@ class ImportScanForm(forms.Form):
525525
source_code_management_uri = forms.URLField(max_length=600, required=False, help_text="Resource link to source code")
526526
tags = TagField(required=False, help_text="Add tags that help describe this scan. "
527527
"Choose from the list or add new tags. Press Enter key to add.")
528-
file = forms.FileField(widget=forms.widgets.FileInput(
529-
attrs={"accept": ".xml, .csv, .nessus, .json, .jsonl, .html, .js, .zip, .xlsx, .txt, .sarif"}),
528+
file = forms.FileField(
529+
widget=forms.widgets.FileInput(
530+
attrs={"accept": ".xml, .csv, .nessus, .json, .jsonl, .html, .js, .zip, .xlsx, .txt, .sarif"},
531+
),
530532
label="Choose report file",
531533
allow_empty_file=True,
532-
required=False)
534+
required=False,
535+
validators=[ImporterFileExtensionValidator()],
536+
)
533537

534538
# Close Old Findings has changed. The default is engagement only, and it requires a second flag to expand to the product scope.
535539
# Exposing the choice as two different check boxes.
@@ -646,11 +650,15 @@ class ReImportScanForm(forms.Form):
646650
endpoints = forms.ModelMultipleChoiceField(Endpoint.objects, required=False, label="Systems / Endpoints")
647651
tags = TagField(required=False, help_text="Modify existing tags that help describe this scan. "
648652
"Choose from the list or add new tags. Press Enter key to add.")
649-
file = forms.FileField(widget=forms.widgets.FileInput(
650-
attrs={"accept": ".xml, .csv, .nessus, .json, .jsonl, .html, .js, .zip, .xlsx, .txt, .sarif"}),
653+
file = forms.FileField(
654+
widget=forms.widgets.FileInput(
655+
attrs={"accept": ".xml, .csv, .nessus, .json, .jsonl, .html, .js, .zip, .xlsx, .txt, .sarif"},
656+
),
651657
label="Choose report file",
652658
allow_empty_file=True,
653-
required=False)
659+
required=False,
660+
validators=[ImporterFileExtensionValidator()],
661+
)
654662
close_old_findings = forms.BooleanField(help_text="Select if old findings in the same test that are no longer present in the report get closed as mitigated when importing.",
655663
required=False, initial=True)
656664
version = forms.CharField(max_length=100, required=False, help_text="Version that will be set on existing Test object. Leave empty to leave existing value in place.")

dojo/validators.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import cvss.parser
66
from cvss import CVSS2, CVSS3, CVSS4
77
from django.core.exceptions import ValidationError
8+
from django.core.validators import FileExtensionValidator
89

910
logger = logging.getLogger(__name__)
1011

@@ -72,3 +73,12 @@ def cvss3_validator(value: str | list[str], exception_class: Callable = Validati
7273
# to avoid 'NoneType' errors during severity processing later.
7374
msg = "No valid CVSS vectors found by cvss.parse_cvss_from_text()"
7475
raise exception_class(msg)
76+
77+
78+
class ImporterFileExtensionValidator(FileExtensionValidator):
79+
default_allowed_extensions = ["xml", "csv", "nessus", "json", "jsonl", "html", "js", "zip", "xlsx", "txt", "sarif"]
80+
81+
def __init__(self, *args: list, **kwargs: dict):
82+
if "allowed_extensions" not in kwargs:
83+
kwargs["allowed_extensions"] = self.default_allowed_extensions
84+
super().__init__(*args, **kwargs)

0 commit comments

Comments
 (0)