refactor(tasks): extract filename regex to shared constant
Move the valid filename regex pattern to a shared constant in `app/utils/filename_utils.py` and update both the task logic and security tests to use it. This eliminates duplication and ensures consistency across the codebase. Changes: - Defined `VALID_FILENAME_PATTERN` and `VALID_FILENAME_RE` in `app/utils/filename_utils.py`. - Updated `app/tasks/extract_metadata_with_gpt.py` to use `VALID_FILENAME_RE`. - Updated `tests/test_path_traversal_security.py` to use `VALID_FILENAME_PATTERN`. This refactoring addresses the duplication mentioned in the TODO in `tests/test_path_traversal_security.py`. Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
@@ -14,6 +14,7 @@ from app.tasks.embed_metadata_into_pdf import embed_metadata_into_pdf
|
|||||||
from app.tasks.retry_config import BaseTaskWithRetry
|
from app.tasks.retry_config import BaseTaskWithRetry
|
||||||
from app.utils import log_task_progress
|
from app.utils import log_task_progress
|
||||||
from app.utils.ai_provider import get_ai_provider
|
from app.utils.ai_provider import get_ai_provider
|
||||||
|
from app.utils.filename_utils import VALID_FILENAME_RE
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -148,12 +149,12 @@ def extract_metadata_with_gpt(self, filename: str, cleaned_text: str, file_id: i
|
|||||||
suggested_filename = metadata.get("filename", "")
|
suggested_filename = metadata.get("filename", "")
|
||||||
if suggested_filename:
|
if suggested_filename:
|
||||||
# Check if filename contains only safe characters AND explicitly check for ".."
|
# Check if filename contains only safe characters AND explicitly check for ".."
|
||||||
# Defense in depth: While the regex [\w\-\. ]+ already excludes / and \,
|
# Defense in depth: While the regex VALID_FILENAME_PATTERN already excludes / and \,
|
||||||
# we explicitly reject ".." to guard against:
|
# we explicitly reject ".." to guard against:
|
||||||
# 1. Potential locale-specific \w behavior
|
# 1. Potential locale-specific \w behavior
|
||||||
# 2. Files literally named ".." which are valid but problematic
|
# 2. Files literally named ".." which are valid but problematic
|
||||||
# 3. Future code changes that might relax the regex
|
# 3. Future code changes that might relax the regex
|
||||||
if not re.match(r"^[\w\-\. ]+$", suggested_filename) or ".." in suggested_filename:
|
if not VALID_FILENAME_RE.match(suggested_filename) or ".." in suggested_filename:
|
||||||
logger.warning(f"[{task_id}] Invalid filename format from GPT: '{suggested_filename}', using fallback")
|
logger.warning(f"[{task_id}] Invalid filename format from GPT: '{suggested_filename}', using fallback")
|
||||||
# Reset to empty to trigger fallback to original filename
|
# Reset to empty to trigger fallback to original filename
|
||||||
metadata["filename"] = ""
|
metadata["filename"] = ""
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ from pathlib import Path
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Pattern for valid filenames (alphanumeric, dash, underscore, period, and space)
|
||||||
|
# Used for validating GPT-provided filenames and other inputs
|
||||||
|
VALID_FILENAME_PATTERN = r"^[\w\-\. ]+$"
|
||||||
|
VALID_FILENAME_RE = re.compile(VALID_FILENAME_PATTERN)
|
||||||
|
|
||||||
|
|
||||||
def get_unique_filename(original_path: str, check_exists_func: Callable[[str], bool] | None = None) -> str:
|
def get_unique_filename(original_path: str, check_exists_func: Callable[[str], bool] | None = None) -> str:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -212,9 +212,10 @@ class TestExtractMetadataFilenameValidation:
|
|||||||
"""Test that invalid filename formats are rejected."""
|
"""Test that invalid filename formats are rejected."""
|
||||||
import re
|
import re
|
||||||
|
|
||||||
# Valid pattern from extract_metadata_with_gpt.py
|
from app.utils.filename_utils import VALID_FILENAME_PATTERN
|
||||||
# TODO: Consider extracting this to a shared constant to avoid duplication
|
|
||||||
valid_pattern = r"^[\w\-\. ]+$"
|
# Valid pattern from app.utils.filename_utils
|
||||||
|
valid_pattern = VALID_FILENAME_PATTERN
|
||||||
|
|
||||||
# Test valid filenames
|
# Test valid filenames
|
||||||
valid_filenames = [
|
valid_filenames = [
|
||||||
|
|||||||
Reference in New Issue
Block a user