diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 9bd8528..94e2dcc 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -1,4 +1,7 @@ ## 2025-02-21 - Path Traversal in Mix Endpoint API Parameter **Vulnerability:** The `/projects/{project_id}/mix` API endpoint in `src/audioformation/server/routes.py` accepted a `music` parameter (meant to specify a filename within the `05_MUSIC/generated` directory) but directly passed it to `mix_project` without sanitization. This allowed directory traversal payloads like `../../../etc/passwd` to be used for background music resolution. **Learning:** Even internal API inputs that map strictly to filenames inside an expected directory must be sanitized. A simple check for file existence (`if not bg_music_path.exists():`) is insufficient as it confirms existence but allows looking outside the bounded directory. -**Prevention:** Always use established sanitization helpers (like `sanitize_filename`) or bound checks (like `validate_path_within`) for any user-supplied string that forms part of a filesystem path. Ensure bypass parameters like `FORCE_NO_MUSIC` are handled before and mutually exclusively from sanitization. \ No newline at end of file +**Prevention:** Always use established sanitization helpers (like `sanitize_filename`) or bound checks (like `validate_path_within`) for any user-supplied string that forms part of a filesystem path. Ensure bypass parameters like `FORCE_NO_MUSIC` are handled before and mutually exclusively from sanitization.## 2025-02-21 - SafeStaticFiles Bypass via AttributeError +**Vulnerability:** The custom `SafeStaticFiles` class designed to block access to sensitive files (like `.env` and `00_config`) failed closed improperly due to an `AttributeError` when doing `Path(path).lower()`. A 500 error on the server side could prevent the static files middleware from properly functioning or bypass the security check completely in certain scenarios depending on exception handling. +**Learning:** Type assumptions must be rigorously checked in security controls. An `AttributeError` in a security blocklist check can render the entire control ineffective or create an accidental DoS. Path string normalizations must happen *before* instantiating pathlib objects. +**Prevention:** Always normalize strings before converting them to strongly-typed objects when using methods that are string-specific (`.lower()`, `.upper()`), and write tests that specifically verify the failure path of security controls. diff --git a/src/audioformation/server/app.py b/src/audioformation/server/app.py index 9334beb..5cf513b 100644 --- a/src/audioformation/server/app.py +++ b/src/audioformation/server/app.py @@ -24,7 +24,7 @@ class SafeStaticFiles(StaticFiles): async def get_response(self, path: str, scope) -> Response: # Normalize path for check - p = Path(path).lower() + p = Path(path.lower()) if "00_config" in p.parts or p.name.startswith(".env") or ".git" in p.parts: raise HTTPException( status_code=403, detail="Access denied to sensitive resource"