TASK-014: Add log path validation to prevent arbitrary file access

Restrict monitored log paths to a configurable allowlist of safe directories
to prevent authenticated users from instructing fail2ban to monitor arbitrary
files on the system, which could leak contents via fail2ban logging.

Changes:
- Add 'allowed_log_dirs' setting to Settings (defaults to /var/log, /config/log)
- Add @field_validator to AddLogPathRequest to validate log paths at request time
- Validator resolves paths to canonical form and checks against allowed prefixes
- Use Path.is_relative_to() to prevent prefix bypass attacks like /var/log_evil
- Add comprehensive tests for valid/invalid paths and symlink handling
- Update Features.md and Backend-Development.md with security documentation

Security improvements:
- Blocks access to sensitive files (/etc/shadow, /etc/passwd, etc.)
- Resolves symlinks before validation to prevent escape routes
- Uses proper path comparison instead of string prefix matching
- Configurable via BANGUI_ALLOWED_LOG_DIRS environment variable

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-26 13:49:04 +02:00
parent 2331567bd7
commit 308cf680a7
5 changed files with 223 additions and 4 deletions

View File

@@ -553,6 +553,35 @@ BANGUI_FAIL2BAN_START_COMMAND='"/opt/my tools/fail2ban" start' # Quoted path
**Common Pitfall:**
Using `.split()` instead of `shlex.split()` would break commands with spaces in paths. Always use quoted strings for paths that contain whitespace.
### Log Path Validation & Allowlisting
Authenticated users can instruct fail2ban to monitor additional log files through the API endpoint `POST /api/config/jails/{name}/logpath`. To prevent path-traversal attacks and unauthorized reads of sensitive system files, all requested log paths must resolve to locations within a configurable allowlist of safe directories.
**Allowed Directories:**
- Configured via the `BANGUI_ALLOWED_LOG_DIRS` environment variable (comma-separated list).
- Defaults to: `["/var/log", "/config/log"]`.
**Path Validation Rules:**
1. The requested path is resolved to its canonical form using `Path(log_path).resolve()`, which:
- Expands relative paths to absolute paths.
- Resolves symbolic links to their real targets.
- Normalizes `.` and `..` components.
2. The resolved path is checked using `Path.is_relative_to()` against each allowed directory prefix.
3. If the resolved path is not relative to any allowed directory, a `ValueError` is raised with a descriptive error message.
**Implementation:**
- Validation occurs in the Pydantic model `AddLogPathRequest` using a `@field_validator`.
- The validator runs at request time, before the service layer is invoked.
- Symlinks that escape allowed directories are rejected (see [symlink bypass tests](../../backend/tests/test_models.py)).
**Important:** Use `is_relative_to()`, not `startswith()` or string prefix matching. The latter is bypassable with paths like `/var/log_evil/file.log`.
**Environment Variables:**
```bash
BANGUI_ALLOWED_LOG_DIRS="/var/log,/config/log" # Default
BANGUI_ALLOWED_LOG_DIRS="/var/log,/config/log,/home/app/logs" # Custom directory
```
### Login Rate Limiting
The login endpoint (`POST /api/auth/login`) is protected against brute-force attacks using an in-memory rate limiter.