Skip to content

Security: urbytes21/linux-esp32s3

Security

SECURITY.md

Security

This is a research project: a general-purpose Linux running on a microcontroller that was never designed to host one. It is meant for a workbench and a trusted home LAN. Do not put a board running this image on an untrusted network, or anywhere the network it joins matters.

Nothing below is a bug report. These are deliberate trade-offs, listed so the choice to accept them is yours and not a surprise.

What the shipped image exposes

The default-credential/network warnings apply to both the older images and the current branch. The new userspace adds private homes, su/passwd and per-user cron. BusyBox is SUID root for the applets that require it; ordinary applets drop privileges. HTTP runs as www-data, and web files are not world-writable. There is no sudo/doas or automatic wheel-group elevation.

These are Unix permission checks, not hardware memory isolation. The NOMMU fork backend does not make untrusted native code safe. Use only trusted users/programs; do not expose cron, shells or editable CGI to hostile users. Raw flash backups can contain passwords, WiFi configuration and user files; keep them private and separate from distributable build artifacts.

Root password changeme123 on every flashed board, until the first login replaces it
Telnet off until the first login picks it, unencrypted — password and session in clear text
SSH off until the first login picks it (remote-login ssh later); port 22, password or key until remote-login port/auth say otherwise; slow on this hardware
Bluetooth LE advertises as Esp32-Linux, no pairing, no PIN
HTTP status page off by default (web-server on enables it, and it stays on across reboots); no auth, plain HTTP
Firewall none. No firewall package ships in the image
Secure boot / flash encryption not used; flash can be read and rewritten over USB

Nothing filters inbound traffic: a port is closed only because no process is listening on it. iptables used to ship with an empty ruleset that changed nothing until you wrote rules; 0.8 removed it entirely to reclaim flash (see the changelog), and there is no other firewall tool on the image.

The password is deliberately an obvious changeme rather than a plausible-looking one, so there is no chance of mistaking it for a real secret. The first login does not hand out a shell until it is changed, and nothing listens on the network before that: a board joined to WiFi over Bluetooth is not reachable with the factory password. The first login then turns on SSH or Telnet, one of them, or neither; ssh-server on can still add SSH next to Telnet by hand. remote-login auth key turns SSH passwords off once a key is in /home/root/.ssh/authorized_keys, which is the setting to use on any network you do not fully trust; a different port only keeps the log quieter.

It asks the internet what time it is

Every time the board joins a network it sends an NTP query to pool.ntp.org and to two IP literals belonging to Cloudflare and Google. That is unsolicited outbound traffic to third parties, and the answer is unauthenticated — plain NTP has no signatures, so whoever can intercept it can set this board's clock to whatever they like, which in turn decides whether an expired certificate looks valid.

It is the same trade every appliance without a battery makes, and the alternative is a board that cannot do HTTPS at all until someone types the date. If you would rather it stayed quiet, delete /usr/share/udhcpc/default.script.d/50-set-clock — but it is on the read-only cramfs, so in practice that means rebuilding the image.

The Bluetooth link is unauthenticated

Anyone within BLE range can connect and reach the WiFi provisioning dialog. It is not a root shell — it only scans and joins networks — but that is enough to move your board onto a network of their choosing, and to list the SSIDs the board can see.

There is no pairing because the point of the feature is joining a network with no PC and no cable, and the dialog has to work before any credentials exist. If that trade is wrong for you, delete /etc/init.d/S46blewifi and reboot; the rest of the system is unaffected.

Past incidents

Any open WiFi network, joined automatically. Buildroot's wpa_supplicant package installs its own /etc/wpa_supplicant.conf containing a network block with no ssid and key_mgmt=NONE, which matches any unencrypted network. A board built from this repo joined a carrier hotspot on its own, unprompted.

The released images never carried the file, but only by accident — it had been deleted by hand from an incremental build tree, and nothing here reproduced that. Fixed by removing it in a post-build script, plus a check in make-images.sh, whose previous check looked only for a psk= line and so missed it entirely: an open-network block contains no credentials at all, which is exactly what makes it dangerous.

If you built from source before that fix, check the board:

cat /etc/wpa_supplicant.conf     # a network block with no ssid is the bad one

Reporting something

Open a GitHub issue. There is no private disclosure channel — this is a single-maintainer hobby project, and pretending otherwise would be worse than saying so. If a finding genuinely should not be public first, open an issue asking for a contact and leave the details out of it.

No support commitment, no fix timeline, no backports. The reproducibility caveats and the list of past build defects are in DEVELOPMENT.md.

There aren't any published security advisories