diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 65407a8..103a4a9 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -21,3 +21,15 @@ Hardcoded credentials pose a critical risk because they provide an easy entry po **Prevention:** 1. Never commit secrets, API keys, or passwords into the source code repository. Always read sensitive configuration using environment variables (e.g., `os.getenv`). 2. Implement secure comparisons utilizing functions designed to prevent timing attacks, like `secrets.compare_digest()`, and properly encode inputs to prevent TypeErrors on non-ASCII characters. + +## 2024-05-20 - Exception Information Leakage in Authentication + +**Vulnerability:** +The `admin_login` route in `main.py` had an overly broad `except Exception as e:` block that directly re-raised unexpected general exceptions as `HTTPException` with `detail=str(e)`. This can inadvertently expose sensitive internal details (e.g., database connection strings, stack traces) to external clients. + +**Learning:** +General exceptions must never leak exact error strings to the user, as they could contain internal context useful for exploitation. + +**Prevention:** +1. Catch specific exceptions (like `HTTPException` for auth/config errors) and explicitly handle them. +2. For unhandled exceptions (`Exception`), log the detailed string internally and return a generic error message (like "An internal error occurred") to the client. diff --git a/main.py b/main.py index 977e1f2..0bba14b 100644 --- a/main.py +++ b/main.py @@ -92,9 +92,12 @@ async def admin_login(login_request: models.LoginRequest, response: Response): sessions[session_id] = login_request.username # Map session ID to username response.set_cookie("session_id", session_id, httponly=True) return {"message": "Login successful"} + except HTTPException: + # Re-raise HTTPExceptions (like 401 Unauthorized or 500 configuration errors) to preserve them + raise except Exception as e: logging.error(f"Login failed for {login_request.username}: {str(e)}") - raise HTTPException(status_code=401, detail=str(e)) # Unauthorized + raise HTTPException(status_code=500, detail="An internal error occurred during login") # Admin logout route @app.post("/admin/logout/")