{"id":"CVE-2026-55419","aliases":["GHSA-m2pc-3q4q-w6jr","PYSEC-2026-3916"],"url":"https://o3.security/vulnerability/CVE-2026-55419","summary":"Reachy Mini: Unrestricted Upload of File with Dangerous Type","details":"## Summary\n\nThe Reachy Mini daemon exposes the “/api/media/sounds/upload” endpoint without authentication and file validation mechanisms.  \nAn attacker can use this endpoint to upload malicious files into the file system that will propagate in future attacks.\n\n## Compromise Chain: Unauthenticated to Full Root Access\n\nThis issue is part of a full compromise chain allowing an unauthenticated user to gain root access on the Reachy’s operating system:\n\n1. Unrestricted File Upload in Media Sounds Upload API \\<= current finding  \n2. Bluetooth Authentication Bypass  \n3. Bluetooth Directory Traversal\n\n\n## Description\n\nThe root cause of the issue is at the handler located in “***src/daemon/app/routers/media.py***” file at the “upload\\_sound” method:\n\n```py\n@router.post(\"/sounds/upload\")\nasync def upload_sound(\n    file: UploadFile = File(...),\n) -> dict[str, str]:\n    \"\"\"Upload a sound file to the daemon's temporary sound directory.\n    The file is saved to ``/tmp/reachy_mini_sounds/<original_filename>``.\n    If a file with the same name already exists it is overwritten.\n    Returns:\n        JSON with the absolute *path* of the saved file on the daemon.\n    \"\"\"\n    if not file.filename:\n        raise HTTPException(status_code=400, detail=\"Filename is required\")\n    # Reject path traversal\n    filename = Path(file.filename).name\n    if not filename or filename in (\".\", \"..\"):\n        raise HTTPException(status_code=400, detail=\"Invalid filename\")\n    os.makedirs(SOUNDS_TMP_DIR, exist_ok=True)\n    dest = os.path.join(SOUNDS_TMP_DIR, filename)\n    content = await file.read()\n    with open(dest, \"wb\") as f:\n        f.write(content)\n    return {\"status\": \"ok\", \"path\": dest}\n```\n\nThis endpoint lacks multiple defence mechanisms:\n\n1. No authentication mechanism.  \n2. No file extension validation.  \n3. No file content/size validation.\n\nAdditionally, the daemon is bound to the 0.0.0.0 network interfaces (a.k.a. all network interfaces) by default along with permissive CORS ( allow\\_origins=\\[“\\*”\\] ) meaning the following API endpoint is exposed to every network interface the daemon is connected to.\n\n# PoC\n\n1. Start the daemon in simulation mode (command depends on the installed environment):\n\n```shell\n .venv/bin/mjpython -m reachy_mini.daemon.app.main --sim --no-media\n```\n\n2. After that check that the media upload API endpoint is activated and you can upload a wav file:\n\n```shell\ncurl -X POST http://<daemon_domain>:<daemon_port>/api/media/sounds/upload \\\n    -F \"file=@/path/to/your/file.wav\"\n```\n\n3. Now attempt to create a “.sh” file containing a script and upload it:\n\n```shell\ncurl -X POST http://<daemon_domain>:<daemon_port>/api/media/sounds/upload \\\n    -F \"file=@/path/to/your/script.sh\"\n```\n\n4. Now error message will be received and you will see that the script file was successfully uploaded to disk.\n\n# Impact\n\nDue to this issue, an attacker can upload malicious files instead of the intended sounds files, harming the integrity of the stored data and allowing an attacker to propagate a foothold in cases another vulnerabilities would arise.\n\n## Fix suggestion\n\nPerform the following check on the API endpoint:\n\n1. Validate that the file extension contains only desired extensions (allow-list approach).  \n2. Validate that the uploaded file’s content matches the desired extension (Magic numbers, and known file structure per file type).  \n3. Enforce authentication on the file upload endpoint.\n\n## Credit\n\nThe vulnerability was discovered by Natan Nehorai of the JFrog Vulnerability Research team.","published":"2026-08-25T17:34:58.892Z","modified":"2026-09-11T03:30:24.857972085Z","cvss":{"score":5.3,"severity":"MEDIUM","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N"},"epss":null,"cisaKev":null,"exploitsKnown":null,"affectedPackages":[{"ecosystem":"PyPI","name":"reachy-mini","fixedVersion":"1.8.2"}],"fix":{"url":"https://github.com/pollen-robotics/reachy_mini/commit/984c7723b3ec5da63f4e0a2bcf9f120ceb563e04","label":"pollen-robotics/reachy_mini@984c772"},"references":[{"type":"WEB","url":"https://github.com/pollen-robotics/reachy_mini/releases/tag/v1.8.2"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/55xxx/CVE-2026-55419.json"},{"type":"ADVISORY","url":"https://github.com/pollen-robotics/reachy_mini/security/advisories/GHSA-m2pc-3q4q-w6jr"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-55419"},{"type":"FIX","url":"https://github.com/pollen-robotics/reachy_mini/commit/984c7723b3ec5da63f4e0a2bcf9f120ceb563e04"},{"type":"FIX","url":"https://github.com/pollen-robotics/reachy_mini/pull/1209"},{"type":"PACKAGE","url":"https://github.com/pollen-robotics/reachy_mini"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-09-11T03:30:24.857972085Z"}}