From 8b07cacb0ae0c8bed655d4768dc12330bc266b27 Mon Sep 17 00:00:00 2001 From: L1nSn0w Date: Fri, 8 May 2026 11:02:51 +0800 Subject: [PATCH] fix(api): reject extensionless files even with empty whitelist entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A whitelist with an empty / whitespace entry (e.g. a stray comma in DSL) combined with an extensionless file would spuriously match — both sides normalize to "" and pass. Filter empty normalized whitelist entries and short-circuit when the input extension itself normalizes to empty, so invalid whitelist entries can't widen the allowlist. Reported by Copilot on PR review. --- api/factories/file_factory/validation.py | 5 ++++- .../unit_tests/factories/test_file_validation.py | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) 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