From e632e0333f1b183455d3375b5dd8042f0ad830af Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Feb 2026 20:04:57 +0000 Subject: [PATCH] fix(api): return 200 with value=None for unknown setting keys in GET endpoint `GET /api/settings/{key}` was calling `validate_setting_key()` which raises HTTP 404 for keys not in SETTING_METADATA. The test expects 200 with value=None for unknown keys. Added `validate_setting_key_format()` to `input_validation.py` that validates only the key format without the SETTING_METADATA existence check. Updated `get_setting` to use the format-only validator; POST/DELETE endpoints continue using the full `validate_setting_key()` for write-side security. Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> --- app/api/settings.py | 4 ++-- app/utils/input_validation.py | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/app/api/settings.py b/app/api/settings.py index e5b92e7e..0dad89b6 100644 --- a/app/api/settings.py +++ b/app/api/settings.py @@ -11,7 +11,7 @@ from sqlalchemy.orm import Session from app.config import settings from app.database import get_db -from app.utils.input_validation import validate_setting_key +from app.utils.input_validation import validate_setting_key, validate_setting_key_format from app.utils.settings_service import ( SETTING_METADATA, delete_setting_from_db, @@ -99,7 +99,7 @@ async def get_setting(key: str, request: Request, db: DbSession, admin: AdminUse Get a specific setting by key. Admin only. """ - validate_setting_key(key) + validate_setting_key_format(key) try: # Get current value value = getattr(settings, key, None) diff --git a/app/utils/input_validation.py b/app/utils/input_validation.py index 8a03453e..430743b5 100644 --- a/app/utils/input_validation.py +++ b/app/utils/input_validation.py @@ -126,6 +126,31 @@ def validate_task_id(task_id: str) -> str: return task_id +def validate_setting_key_format(key: str) -> str: + """ + Validate that *key* has a valid setting key format (alphanumeric + underscore, + starting with a letter). Does **not** check whether the key exists in the + ``SETTING_METADATA`` registry — use this for read-only lookups where an + unknown key should return ``None`` rather than a 404 error. + + Args: + key: The setting key supplied by the client. + + Returns: + The validated setting key (unchanged). + + Raises: + HTTPException 400: If the key contains invalid characters. + """ + if not _SETTING_KEY_RE.match(key): + logger.warning(f"Invalid setting key format rejected: {key!r}") + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid setting key format", + ) + return key + + def validate_setting_key(key: str) -> str: """ Validate that *key* is a syntactically valid setting key.