What My EMO Robot Says on the Wire

securityiotnetworking

EMO is a small desktop robot with a face, a microphone, and a cloud account. It listens, talks back, and generally acts like a pet. It also sits on my home Wi-Fi, which made me curious what it’s actually saying to the internet when nobody’s looking. So I built it a network of its own and watched.

The setup

A throwaway access point on a spare USB Wi-Fi adapter, WPA2, its own subnet, NAT out through the laptop’s real connection. dnsmasq handed out addresses and logged every DNS lookup; tcpdump recorded everything on the AP side. EMO, its charging dock, and later my phone were the only things on it. Total capture: about 45 minutes of poking, chatting, docking, undocking, and sitting quietly in a silent room.

I’ll own the first mistake: for the first twenty minutes EMO had no internet at all, and played a sad error tone at me. I’d named an nftables chain fwd, which turns out to be a reserved word, so the NAT rules never loaded and EMO’s connection attempts just went unanswered. Renamed the chains, and it came to life. (Also a good reminder that “the device is broken” and “my firewall config silently didn’t load” look identical from the device’s side.)

The good news

The main channel is TLS on port 443, so I can only see sizes and timing there. The pattern is what you’d hope for: every time I talked to EMO, a burst of 60–280 KB went up, right around the size of a few seconds of compressed audio. When I was quiet, nothing did. I didn’t try to break the encryption or check whether EMO validates certificates, so I can’t say anything about the contents.

The less good news

Spoken replies come down over plain HTTP. After each interaction, EMO fetches an MP3 of its reply with a request like this:

GET /mp3/download/<timestamp>.mp3?id=<n>&token=<64 hex characters> HTTP/1.1
Host: eu-tts.living.ai
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) ... Chrome/47.0.2526.80 Safari/537.36

Port 80, no TLS. Anyone on the network path — same Wi-Fi, an ISP, any hop in between — can read the request and download the audio. The URL even carries its own credential in the token parameter, so a captured URL is enough to fetch that clip. I pulled ten clips straight out of the capture. (I haven’t played them, so I can’t tell you what they say.)

How bad is that? Honestly, moderate. The voice I send up seems to travel inside the TLS connection, so what leaked was the robot’s answers, not my side of the conversation. But replies can be personal — names, reminders, whatever you’ve told it — and an attacker doesn’t need to compromise anything, just share a network with it. The ancient Chrome 47 user-agent string is a smaller smell pointing at the same thing: an HTTP client that hasn’t been touched in a long time.

A broadcast with the device ID in it. EMO periodically shouts a UDP packet at 255.255.255.255 port 2349, ten copies in about a second, in plaintext JSON that includes its device identifier and a command called master_call. It looks like local discovery. Nobody answered, ever, including my phone. I saw it three times in 45 minutes and couldn’t tie any of them to something I did — the first one came before I’d even put EMO on its dock. Everyone on the local network can see it; it isn’t routable beyond that, so the exposure is limited to whoever’s already on your Wi-Fi. Low severity, but it’s an identifier broadcast in the clear.

What I haven’t tested

I’d rather be clear about the edges of this:

What I’d do about it

If you own one: put it on a guest network or its own SSID so the only people who can sniff its clips are the ones you’ve already given your Wi-Fi password to. That’s cheap and covers both findings. Beyond that, the real fix is on the vendor’s side — serve the clips over HTTPS — and the next step for me is a replay test using only my own captured URLs, then telling them what I found.

Overall: a lot less chatty than I expected. One server, no open ports, silent when idle. It’s just that one plaintext HTTP request undoes some of the good work.