Fix: Remove socket path leak in fail2ban error responses
- Change _fail2ban_connection_handler() to return generic message instead of leaking socket path in HTTP 502 response body - Change _fail2ban_protocol_handler() to return generic message instead of leaking raw exception details in HTTP 502 response body - Full error details are still logged server-side (error=str(exc)) for debugging - Update Backend-Development.md with error message hygiene section explaining the pattern: generic user-friendly messages in HTTP responses, full details in server logs only Fixes TASK-029: Fail2BanConnectionError leaks socket path in HTTP error responses Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,47 +1,3 @@
|
||||
## TASK-028 — Fire-and-forget `asyncio.create_task()` silently discards exceptions
|
||||
|
||||
**Severity:** Low
|
||||
|
||||
### Where found
|
||||
`backend/app/services/ban_service.py` line ~614:
|
||||
```python
|
||||
asyncio.create_task( # noqa: RUF006
|
||||
geo_cache.lookup_batch(uncached, http_session, db=app_db),
|
||||
name="geo_bans_by_country",
|
||||
)
|
||||
```
|
||||
|
||||
### Why this is needed
|
||||
The task reference is immediately discarded. Any exception raised inside `geo_cache.lookup_batch()` — network errors, aiohttp timeouts, DB write failures — becomes an unhandled task exception. In Python 3.11+ this emits a `RuntimeWarning` to stderr but is otherwise silently swallowed. Errors in background geo resolution are invisible in structured logs.
|
||||
|
||||
### Goal
|
||||
Ensure exceptions in fire-and-forget tasks are always logged.
|
||||
|
||||
### What to do
|
||||
1. Wrap the task body in a logging wrapper:
|
||||
```python
|
||||
async def _logged_task(coro: Coroutine[Any, Any, Any], name: str) -> None:
|
||||
try:
|
||||
await coro
|
||||
except Exception:
|
||||
log.exception("background_task_failed", task_name=name)
|
||||
|
||||
asyncio.create_task(_logged_task(geo_cache.lookup_batch(...), "geo_bans_by_country"))
|
||||
```
|
||||
2. Extract `_logged_task` into `backend/app/utils/async_utils.py` as a reusable helper so the same pattern is used for all fire-and-forget tasks.
|
||||
|
||||
### Possible traps and issues
|
||||
- The done callback must not re-raise the exception — only log it.
|
||||
- `log.exception()` inside a callback/task captures the traceback automatically with structlog.
|
||||
|
||||
### Docs changes needed
|
||||
- `Backend-Development.md` — fire-and-forget task conventions.
|
||||
|
||||
### Doc references
|
||||
- [Backend-Development.md](Backend-Development.md) — async patterns
|
||||
|
||||
---
|
||||
|
||||
## TASK-029 — `Fail2BanConnectionError` leaks socket path in HTTP error responses
|
||||
|
||||
**Severity:** Medium
|
||||
|
||||
Reference in New Issue
Block a user