ATH-MaaS/Pixelle-Video · warning · HTTPException

Access denied

Error message

Access denied

What it means

If abs_path.relative_to(Path.cwd()) raises ValueError — meaning the resolved path is not under the server's working directory at all (e.g. an absolute path elsewhere on the system) — the handler returns a bare 403 'Access denied'. It is the fallback branch of the same traversal protection as the prefix whitelist.

Source

Thrown at api/routers/files.py:97

        
        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',
        }
        media_type = media_types.get(suffix, 'application/octet-stream')
        
        # Use inline disposition for browser preview
        return FileResponse(

View on GitHub (pinned to 848b054e4f)

Solutions

  1. Use paths within the server's working directory (e.g. output/...).
  2. Start the server from the project root so Path.cwd() matches expectations.
  3. If an external directory must be served, extend the handler to allowlist it explicitly (not by bypassing the check).
  4. Inspect how full_path is configured/defaulted for your deployment.

Example fix

# before
full_path = "/var/data/media/video.mp4"   # outside server CWD
# after
full_path = "output/video.mp4"            # resolved under Path.cwd()
Defensive patterns

Strategy: validation

Validate before calling

import path from 'path';
const abs = path.resolve(fullPath ?? path.join('output', filePath));
const cwd = process.cwd();
if (!abs.startsWith(cwd + path.sep)) throw new Error('Requested file resolves outside the server working directory');

Prevention

When it happens

Trigger: GET to the files endpoint with a file_path/full_path that resolves outside Path.cwd() entirely — absolute paths like /etc/..., or full_path overrides pointing to other locations — so relative_to() raises ValueError.

Common situations: Configuring full_path to an absolute directory outside the project; running the server from a different CWD than expected so legit paths appear 'outside'; attempting to serve files from another mount point without adjusting the handler.

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.

Related errors


AI-assisted analysis of ATH-MaaS/Pixelle-Video@848b054e4f (2026-08-30). Data as JSON: /api/errors/d9945a4fbd67d6ba. Report an issue: GitHub.