diff --git a/api/factories/file_factory/validation.py b/api/factories/file_factory/validation.py index 15b8a98eef..86dd06990f 100644 --- a/api/factories/file_factory/validation.py +++ b/api/factories/file_factory/validation.py @@ -15,7 +15,10 @@ def _normalize_extension(extension: str) -> str: def _extension_matches(extension: str, whitelist: Iterable[str]) -> bool: - return _normalize_extension(extension) in {_normalize_extension(e) for e in whitelist} + normalized = _normalize_extension(extension) + if not normalized: + return False + return normalized in {ne for e in whitelist if (ne := _normalize_extension(e))} def is_file_valid_with_config( diff --git a/api/tests/unit_tests/factories/test_file_validation.py b/api/tests/unit_tests/factories/test_file_validation.py index 02e882a675..61337fcf10 100644 --- a/api/tests/unit_tests/factories/test_file_validation.py +++ b/api/tests/unit_tests/factories/test_file_validation.py @@ -145,3 +145,15 @@ def test_normalize_handles_whitespace_and_empty_consistently(): allowed_file_extensions=[noisy_entry], ) assert _validate(input_file_type="custom", file_extension=".png", config=config) is False + + +def test_empty_extension_does_not_spuriously_match_empty_whitelist_entry(): + """Defensive: even if the whitelist contains an empty / whitespace entry + (e.g., a stray comma in DSL), an extensionless file must not pass via + a both-sides-empty match. Real entries in the same whitelist still match.""" + config = FileUploadConfig( + allowed_file_types=[FileType.CUSTOM], + allowed_file_extensions=["", ".png"], + ) + assert _validate(input_file_type="custom", file_extension=".png", config=config) is True + assert _validate(input_file_type="custom", file_extension="", config=config) is False