ATH-MaaS/Pixelle-Video · warning · HTTPException
Access denied: only {', '.join(p.rstrip('/') for p in allowe
Error message
Access denied: only {', '.join(p.rstrip('/') for p in allowed_prefixes)} directories are accessible What it means
The handler enforces a path-traversal whitelist: the resolved relative path must start with one of the allowed prefixes (e.g. output/, uploads/). If the file resolves outside those directories it returns 403 with the list of allowed directories. This blocks access to arbitrary server files.
Source
Thrown at api/routers/files.py:92
abs_path = Path.cwd() / full_path
if not abs_path.exists():
raise HTTPException(status_code=404, detail=f"File not found: {file_path}")
if not abs_path.is_file():
raise HTTPException(status_code=400, detail=f"Path is not a file: {file_path}")
# Security: only allow access to specified directories
try:
rel_path = abs_path.relative_to(Path.cwd())
rel_path_str = str(rel_path)
# Check if path starts with any allowed prefix
is_allowed = any(rel_path_str.startswith(prefix.rstrip('/')) for prefix in allowed_prefixes)
if not is_allowed:
raise HTTPException(
status_code=403,
detail=f"Access denied: only {', '.join(p.rstrip('/') for p in allowed_prefixes)} directories are accessible"
)
except ValueError:
raise HTTPException(status_code=403, detail="Access denied")
# Determine media type
suffix = abs_path.suffix.lower()
media_types = {
'.mp4': 'video/mp4',
'.mp3': 'audio/mpeg',
'.wav': 'audio/wav',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.html': 'text/html',
'.json': 'application/json',View on GitHub (pinned to 848b054e4f)
Solutions
- Request only files under the allowed directories (the detail lists them).
- If a new storage directory is legitimate, add it to allowed_prefixes in the handler config.
- Normalize/resolve the requested path client-side to stay within the allowed root.
- Check for symlinks in your output directories that resolve outside the project root.
- Never attempt traversal (../) — the server resolves and rejects it by design.
Example fix
# before GET /api/files/../../etc/passwd # after GET /api/files/generated/frame_0001.mp4 # stays under output/
Defensive patterns
Strategy: validation
Validate before calling
const normalized = path.posix.normalize(filePath).replace(/^\.\./, '');
if (normalized.startsWith('..') || path.isAbsolute(normalized)) throw new Error('Path must be relative and within allowed directories');
const allowedPrefixes = ['output/', 'uploads/'];
if (!allowedPrefixes.some(p => normalized.startsWith(p))) throw new Error(`Only ${allowedPrefixes.join(', ')} paths are servable`); Prevention
- Keep generated artifacts inside the server's allowed directories.
- Never send traversal sequences or absolute paths to file endpoints.
- Avoid symlinks in output directories that point outside the project root.
- When adding new storage locations, update the server's allowed_prefixes list.
When it happens
Trigger: GET to the files endpoint where the resolved path escapes the allowed roots — absolute paths outside CWD, '../' traversal sequences, symlinks pointing outside allowed directories, or requesting files from a directory not in allowed_prefixes.
Common situations: Trying to read config/secrets via path traversal (correctly blocked); legitimate files stored in a new directory that was never added to allowed_prefixes; symlinked output directories resolving outside CWD in dev setups.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of ATH-MaaS/Pixelle-Video@848b054e4f (2026-08-30).
Data as JSON: /api/errors/7de3cd17be4b52ea.
Report an issue: GitHub.