{"id":"CVE-2026-55419","aliases":["GHSA-m2pc-3q4q-w6jr","PYSEC-2026-3916"],"title":"reachy_mini Allows Unrestricted Upload of File with Dangerous Type","summary":"reachy_mini Allows Unrestricted Upload of File with Dangerous Type","severity":"medium","cvss":5.3,"cvssVector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N","vendor":"reachy-mini","product":"reachy-mini","ecosystem":"pip","affected":["reachy-mini < 1.8.2"],"patched":["reachy-mini 1.8.2"],"published":"2026-08-25","updated":"2026-09-10","sourceUpdated":"2026-09-10T12:25:30.194383495Z","source":"OSV","sourceUrl":"https://osv.dev/vulnerability/GHSA-m2pc-3q4q-w6jr","references":[{"url":"https://github.com/pollen-robotics/reachy_mini/security/advisories/GHSA-m2pc-3q4q-w6jr"},{"url":"https://github.com/pollen-robotics/reachy_mini/commit/984c7723b3ec5da63f4e0a2bcf9f120ceb563e04"},{"url":"https://github.com/pollen-robotics/reachy_mini"},{"url":"https://pypi.org/project/reachy-mini"},{"url":"https://github.com/advisories/GHSA-m2pc-3q4q-w6jr"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-55419"},{"url":"https://github.com/pollen-robotics/reachy_mini/pull/1209","label":"security-advisories@github.com"},{"url":"https://github.com/pollen-robotics/reachy_mini/releases/tag/v1.8.2","label":"security-advisories@github.com"}],"tags":["osv","pip","nvd","ghsa"],"epss":0.00339,"epssPercentile":0.2737,"cwe":["CWE-434"],"ingestedAt":"2026-08-25T18:30:21.427Z","slug":"CVE-2026-55419","body":"## Overview\n\n## 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.\n\n## Affected packages\n\n- `reachy-mini < 1.8.2`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `reachy-mini 1.8.2`","depth":"sunlit","depthScore":29,"depthScoreParts":{"impact":29.2,"likelihood":0.1,"exploitation":0,"ransomware":0},"changes":[]}