CVE-2026-55488: motionEye Absolute Path Traversal in Media File Handlers
motionEye's media playback and download endpoints accept a user-supplied filename that can be an absolute path, letting anyone with access read arbitrary files off the server.

The problem
Multiple media handlers in motionEye before 0.44.0 pass a user-controlled filename directly to `os.path.join(target_dir, path)`. When the supplied path is absolute, Python silently discards `target_dir` and returns the attacker's path as-is.
To make things worse, `MoviePlaybackHandler` overrides both `get_absolute_path()` and `validate_absolute_path()` to return the path unchecked, intentionally bypassing Tornado's built-in boundary enforcement. An attacker can therefore read any file the motionEye process has permission to open, including `/etc/motioneye/motion.conf`, SSH keys, and `/etc/passwd`.
On default installs where the normal-user password is empty, the endpoint is reachable without any credentials at all.
Proof of concept
GET /movie/1/playback//etc/motioneye/motion.conf HTTP/1.1
Host: target:8765
# --path-as-is is required with curl to prevent the client from normalising the double slash
# curl --path-as-is -s "http://target:8765/movie/1/playback//etc/motioneye/motion.conf"
# Same primitive works on the download and preview endpoints:
# GET /movie/1/download//etc/passwd
# GET /picture/1/download//etc/passwd
# GET /picture/1/preview//etc/passwdThe root cause is a two-part failure. First, `get_media_path()` in `mediafiles.py` calls `os.path.join(target_dir, path)` without checking whether `path` is absolute. Python's documented behaviour for `os.path.join` is that any absolute component discards all previous components, so supplying `/etc/passwd` as `path` yields `/etc/passwd`, not `<target_dir>/etc/passwd`.
Second, `MoviePlaybackHandler` (and equivalent download/preview handlers) deliberately override Tornado's `get_absolute_path()` and `validate_absolute_path()` safety hooks to return the path unchanged, removing the last safety net. No check for absolute paths, `..` sequences, or canonical-path boundary enforcement existed in these handlers before the patch.
PR #3324 by @MichaIng extended the backend input-path validation so that any supplied path is resolved with `os.path.realpath()` and verified to remain within the camera's configured `target_dir` before the file is served. The overridden Tornado hooks were also corrected to not bypass this check.
The fix
Upgrade to motioneye 0.44.0 or later. The fix (PR #3324) adds a canonical-path check using `os.path.realpath()` to every media handler and removes the unchecked overrides of Tornado's path-validation hooks. As a short-term workaround, restrict network access to port 8765 and set a non-empty normal-user password so the endpoint is not reachable unauthenticated.
Reported by pizza-power, sermikr0, C4spr0x1A, MichaIng, alanturing881.