a note on security with CircuitPython


i quite like CircuitPython, as it means i don't have to deal with using C just to make a microcontroller do something simple these days. it's easy to program and flexible, and especially good for building your own little peripherals that connect into a computer. but unfortunately, this ease of programming continues after you're done programming it yourself, and extends to potential attackers as well! by default, CircuitPython exposes both a USB filesystem and serial console that can reprogram the device, and while these are wonderful for prototyping, if left exposed in a finished device; someone could use them to get up to mischief!

for a practical example — and what inspired me to write about this — let's imagine a keyboard running the CircuitPython-based KMK. now, you might assume that the USB filesystem is the only way you could reprogram the thing, so you do the sensible thing and disable that. now we're safe from any would-be evil maids!

boot.py
import storage
storage.disable_usb_drive()

except now you've gone and done it! because when you disabled USB storage, now that debug console has gained the ability to upload code too! yeah, for some reason if the USB filesystem isn't mounted then the code running via CircuitPython gains write access to that filesystem. and since you can get into the REPL and run code on the board over the debug console, some miscreant could easily, say… sneak in and add a bit of code that starts saving every keystroke to the internal storage. a keylogger dropped inside without you even noticing, hiding on the hardware itself!

…okay, that wouldn't be very useful if you're just using a wired board, since they'd have to come back later and get the data off anyways. and since they need to have serial console access they might as well just run a software keylogger on your machine. so this really isn't that huge of a security vulnerability. still, it's easy enough to mitigate; just disable the serial console as well when you aren't using it.

boot.py
import usb_cdc
usb_cdc.disable()