A keyboard is made by moulding plastic switch parts and keycaps, building a printed circuit board that wires every switch into a grid of rows and columns, and soldering on a small microcontroller that scans that grid hundreds or thousands of times a second. The microcontroller runs firmware that turns closed switches into USB HID reports or Bluetooth LE notifications, and that firmware is flashed and tested at the factory and can usually be replaced later through a bootloader. Wireless models add a radio, a battery and a pairing step, and the security of the whole device rests on how that firmware and that pairing were built.
This post goes one level deeper than our builds of a laptop and a desktop PC, where the keyboard was one line in a parts list. For the board itself see how a printed circuit board is made, for the chip see how semiconductors are made, for USB threats in general see USB risks, BadUSB, lost drives and air gapped transfer, and for the Bluetooth side see Bluetooth LE GATT, pairing, bonding and attribute security.
Keyboard makers do not publish their moulding recipes, yields or switch test rigs. Where a standard or an official project document gives a number, we cite it. Where none does, we describe the step without inventing a figure, and any arithmetic below is labelled illustrative.
Key takeaways
- A keyboard has seven main parts: switches (or a membrane), an optional plate, a PCB with a key matrix and usually one diode per key, a microcontroller, a USB or wireless interface, a case, and keycaps.
- Switches come in several sensing families. Mechanical and membrane switches close an electrical contact; optical switches interrupt a light beam; Hall effect switches measure a magnet's field; capacitive designs measure a change in capacitance. Only contact based switches need classic debouncing.
- The controller scans the matrix by driving one column at a time and reading the rows. Diodes stop "ghost" keys when several keys are held at once, a mechanism the open source QMK documentation walks through step by step.
- Over USB, a keyboard is a Human Interface Device. The USB HID 1.11 specification (2001) defines an 8 byte boot keyboard report with room for six ordinary keys plus modifiers, which is where "6 key rollover" comes from. N key rollover needs a different report layout in the device's report descriptor.
- Keyboard firmware is usually updated through a bootloader. Many open source keyboards use a USB DFU or UF2 bootloader, and the USB DFU 1.1 specification (2004) leaves image verification to the vendor: it defines how bytes move, not who signed them.
- Bluetooth LE keyboards use the HID over GATT Profile, adopted with a revision date of 27 December 2011, which requires bonding and an encrypted link. Proprietary 2.4 GHz dongles follow whatever the vendor designed, and CERT/CC warned in February 2016 that several used protocols without proper encryption.
- Hosts trust keyboards by default. The Linux kernel documentation states plainly that, by default, all USB devices are authorized. Device allow lists, port controls and procurement rules are how organisations narrow that trust.
Raw material to boxed keyboard: the step table
This is the map for the rest of the post. It names the check at each stage rather than a pass rate, because no maker we could find publishes one.
| Step | Input | What happens | Typical checks | Output |
|---|---|---|---|---|
| 1. Resin and compounding | ABS, PBT, polycarbonate and nylon pellets, colourants | Plastic is dried and coloured for housings, stems, keycaps and cases | Moisture content, colour match | Ready to mould resin |
| 2. Switch part moulding | Resin, steel tool moulds | Injection moulding forms switch housings and stems; springs are coiled from steel wire; contact leaves are stamped from copper alloy and plated | Dimensional checks, flash and short shots, spring force samples | Switch components |
| 3. Switch assembly | Housings, stems, springs, contacts or magnets | Parts are assembled and closed; mechanical switches get contacts, Hall effect switches get a magnet in the stem, optical switches get a shutter | Force curve and travel sampling, contact resistance or signal checks, lifecycle samples | Finished switches |
| 4. Keycap moulding and legends | ABS or PBT resin | Caps are moulded once or twice (doubleshot); legends are added by second shot, dye sublimation, laser or printing | Fit on stems, legend sharpness, wear tests on samples | Keycap sets |
| 5. Bare PCB fabrication | Copper clad laminate | Traces for the key matrix, USB lines and antenna are etched, drilled, plated, masked and finished | Electrical test for opens and shorts | Bare board |
| 6. Controller silicon | Wafer from a chip foundry | Microcontroller with USB, and on wireless boards a Bluetooth or 2.4 GHz radio, is fabricated and packaged | Wafer probe and final test at the chip maker | Packaged MCU or radio SoC |
| 7. SMT assembly | Bare PCB, MCU, diodes, crystal, connector, ESD parts, LEDs, battery charger | Solder paste, pick and place, reflow; switch sockets or switches added | Automated optical inspection, X ray on fine pitch parts | Assembled PCB |
| 8. Bootloader and firmware flash | Assembled PCB, signed or unsigned images | A programmer writes the bootloader, then the application firmware, over SWD, JTAG or USB; wireless boards get a device address and calibration | Readback or checksum, version string check, USB enumeration | Programmed PCB |
| 9. Board functional test | Programmed PCB | A fixture presses or shorts every matrix position, checks LEDs, USB descriptors, and on wireless boards radio power and pairing | Every key reports the right usage; current draw; RF test | Tested PCB |
| 10. Final assembly | PCB, plate, switches, stabilisers, case, battery, keycaps | Plate and switches fit, stabilisers lubricated, case closed, caps pressed on | Full keypress test on the finished keyboard, visual inspection | Finished keyboard |
| 11. Compliance and packing | Finished keyboard | Sample units go through emissions testing and, for radios, intentional radiator rules; units are labelled, boxed with cable or dongle | Regulatory labels, serial and firmware version recorded | Boxed keyboard |
Two rows matter most for security. Step 8 is where the code that will run on the keyboard for years is chosen and written, and step 9 is the last point at which a factory confirms the device announces itself as what it claims to be.
A dated timeline of keyboard standards and research
| Date | Event | Why it matters | Source |
|---|---|---|---|
| 27 June 2001 | USB HID Device Class Definition 1.11 published | Defines report descriptors, the boot protocol and the 8 byte boot keyboard report still used today | USB-IF HID 1.11 |
| 5 August 2004 | USB Device Firmware Upgrade specification 1.1 | Standard way to move a firmware image into a USB device; verification left to the vendor | USB-IF DFU 1.1 |
| 2007 | Linux USB device authorization feature | Lets the operating system hold a new USB device unconfigured until it is approved | Linux kernel docs; USBGuard |
| 27 December 2011 | HID over GATT Profile 1.0 revision date | Defines Bluetooth LE keyboards, mice and other HID devices, with mandatory bonding and encryption | Bluetooth SIG HOGP 1.0 |
| 2014 | "BadUSB, On Accessories that Turn Evil" briefing at Black Hat USA | Showed that reprogrammed USB controller firmware can make a device spoof other device types | Black Hat USA 2014 archive |
| 24 February 2016 | CERT/CC Vulnerability Note VU#981271 | Several wireless keyboard and mouse products used proprietary 2.4 GHz protocols without proper encryption | CERT/CC |
| 1 February 2021 | CISA "Using Caution with USB Drives" | Plain language guidance on USB device risks for individuals and organisations | CISA |
| 26 January 2024 | HID Usage Tables 1.5 | Current table of usage codes, including the Keyboard/Keypad page (0x07) | USB-IF HUT 1.5 |
| 20 June 2025 | ZMK project asks users to pin firmware versions | Shows that open source keyboard firmware is now a versioned dependency you should pin | ZMK blog |
What is inside a keyboard?
Pull the keycaps and unscrew the case of almost any keyboard and you find the same layers, in roughly this order from the top.
Keycaps
Keycaps are the moulded caps your fingers touch. They carry the legends and set the feel of the surface. They clip onto the switch stems, so on most mechanical boards they are interchangeable.
Switches or a membrane
Under each cap sits a switch. On a mechanical or magnetic board it is a discrete component, soldered or pressed into a socket. On most office and laptop keyboards there is no discrete switch at all: a rubber dome sheet pushes down on a printed membrane, or a scissor mechanism guides the cap onto a dome.
Plate
Many mechanical boards hold the switches in a steel, aluminium, brass, polycarbonate or FR4 plate. The plate keeps switches aligned and takes the load of typing off the solder joints. Some boards are plateless and rely on the PCB alone.
Stabilisers
Long keys such as the space bar, Shift and Enter use a wire stabiliser so the cap goes down level no matter where you press it. Stabilisers are a frequent source of rattle and are often lubricated at assembly.
PCB, diodes and the key matrix
The printed circuit board wires each switch into a grid of rows and columns, called the key matrix. On mechanical boards there is usually one small diode per switch, which stops phantom key presses when several keys are held. Membrane keyboards build the same grid out of printed conductive traces on plastic sheets instead of copper on fibreglass.
Controller
A microcontroller unit (MCU) scans the matrix, debounces it, maps positions to key codes and talks to the computer. On a wired board it needs a USB peripheral. On a wireless board the MCU is often a radio system on chip with Bluetooth LE, a proprietary 2.4 GHz mode or both, plus a battery charger and fuel gauge.
Interface, case and extras
A USB connector or a battery and antenna, the case, and sometimes backlight LEDs, a rotary encoder, a small display or a USB hub. Several extras add their own firmware or USB interfaces.
How are key switches made?
Mechanical switches
A typical mechanical switch has a two part housing, a stem, a coil spring and a pair of metal contact leaves. The housing and stem are injection moulded from engineering plastics; the spring is coiled from steel wire; the contact leaves are stamped from a copper alloy sheet and plated to resist corrosion. Pressing the key pushes the stem down, which lets one contact leaf touch the other and close a circuit. The shape of the stem and leaf set whether the switch feels linear, tactile (a bump) or clicky (a bump plus a sound from a separate click mechanism).
Because two pieces of metal meet, they bounce. For a few milliseconds after a press or release, the contacts can open and close several times, and a fast scanner would read that as several keystrokes. Firmware hides this with debouncing, covered below.
Makers rate switch lifetimes in keystrokes, and those ratings are vendor test claims under their own conditions. Wear shows up as scratchy feel, changing force or, in contact switches, intermittent chatter as contacts oxidise or deform.
Membrane and rubber dome switches
A membrane keyboard uses three thin sheets of polyester film. The top and bottom sheets are printed with conductive ink traces and pads; the middle sheet is a spacer with holes under each key. Above them sits a sheet of moulded silicone domes. Pressing a key collapses its dome, which pushes the top pad through the spacer hole onto the bottom pad and closes the circuit. Scissor switches in laptops add a pair of interlocking plastic arms that keep a thin cap level while it presses a dome. These parts are cheap to make in large sheets, quiet, and resistant to small spills, which is why most office keyboards use them. They still bounce, so they still need debouncing.
Optical switches
An optical switch places an infrared emitter and a detector on the PCB on either side of the switch. The stem carries a shutter that blocks or unblocks the beam when pressed. There are no contacts to bounce or oxidise, so the debounce problem largely goes away, though firmware still filters noise. The trade off is power: the emitters have to be pulsed, which matters on battery boards.
Hall effect magnetic switches
A Hall effect switch puts a small permanent magnet in the stem and a Hall effect sensor on the PCB under each key. As the stem moves, the magnetic field at the sensor changes and the sensor produces an analogue voltage that the controller reads. Because the controller sees a continuous position rather than a single on or off, firmware can set the actuation point per key, or report a key press as soon as the key starts moving back up (often marketed as "rapid trigger"). Calibration matters: magnets and sensors vary, so these boards usually calibrate each key at the factory or on first use, and store the results in firmware or non volatile memory.
Capacitive switches
Capacitive designs measure a change in capacitance as a conical spring or a plate approaches a pad on the PCB, again without metal contacts. Like magnetic switches, they need analogue sensing circuitry and per key thresholds in firmware.
Comparison: switch sensing methods
| Switch type | What is sensed | Debounce need | Main wear mechanism | Adjustable actuation |
|---|---|---|---|---|
| Mechanical (contact leaf) | Metal contacts touching | High; contacts bounce | Contact wear, oxidation, spring fatigue | No, fixed by the leaf |
| Membrane or rubber dome | Printed pads pressed together | High | Dome fatigue, trace cracking | No |
| Scissor over dome | Printed pads under a dome | High | Dome and hinge wear | No |
| Optical | Infrared beam blocked or unblocked | Low; filter noise only | Spring and housing wear, emitter ageing | Usually no |
| Hall effect magnetic | Magnetic field strength at a sensor | Low; filter noise and drift | Spring wear, magnet or sensor drift | Yes, set in firmware |
| Capacitive | Change in capacitance at a pad | Low; threshold tuning | Spring and dome wear | Sometimes, in firmware |
Debounce, in numbers
The open source QMK firmware documentation sets its default debounce time at 5 milliseconds and lets a board change it with a single line in config.h. It describes two families of algorithm. An "eager" algorithm reports a change immediately, then ignores further changes for the debounce time, which is fast but not resistant to electrical noise. A "defer" algorithm waits until there have been no changes for the debounce time, then reports, which resists noise at the cost of latency. QMK's sym_defer_g applies one global timer to the whole keyboard; sym_defer_pk keeps a timer per key.
Worked example (illustrative). Suppose a contact bounces for 3 ms after a press and the board uses a 5 ms deferred debounce with a 1 ms USB polling interval. The firmware sees the first change at t = 0, sees changes until t = 3 ms, then waits 5 quiet milliseconds and reports the key at about t = 8 ms. The host then picks it up at the next poll, so up to 1 ms more, for a total of up to about 9 ms. An eager algorithm would report at t = 0 and pick it up within 1 ms, but a single noise spike could also produce a false press. That is the trade the debounce setting makes, and it is why magnetic and optical boards advertise lower latency: they have less bounce to wait out.
How are keycaps made?
ABS versus PBT
Most keycaps are moulded from one of two plastics. ABS (acrylonitrile butadiene styrene) moulds easily, takes colour well and is common on office and gaming boards; over time the surface of frequently used ABS caps tends to polish and look shiny. PBT (polybutylene terephthalate) is harder to mould accurately because it shrinks more as it cools, but it resists wear and shine better and has a drier, textured feel. Neither is a security property, but the choice drives which legend method a maker can use.
Doubleshot moulding
Doubleshot keycaps are moulded twice. The first shot forms the legend in one colour of plastic; the second shot moulds the cap body around it in another colour. The legend goes all the way through the wall of the cap, so it cannot wear off. The tooling is expensive and every legend needs its own mould detail, which is why doubleshot sets tend to have fewer language variants.
Dye sublimation
Dye sublimation prints the legend onto the cap with a dye that, under heat, diffuses into the plastic below the surface. It works best on PBT and with dark legends on light caps, because the dye cannot lighten a darker plastic.
Laser etching and printing
Laser etching burns or foams the surface to create a contrasting legend, and lasers can also remove a painted coating to reveal a backlit translucent layer underneath. Pad printing and UV printing put ink on the surface; it is cheap and flexible but wears faster on high use keys. Backlit "shine through" caps use a translucent base that is painted and then laser cut.
| Legend method | Durability | Works on | Typical use |
|---|---|---|---|
| Doubleshot | Legend cannot wear off | ABS and PBT | Enthusiast and premium sets, backlit caps |
| Dye sublimation | Very durable, below the surface | Mostly PBT, light caps | Enthusiast sets with dark legends |
| Laser etched or laser cut paint | Durable to fairly durable | ABS and PBT | Office keyboards, backlit laptops |
| Pad or UV printed | Wears on heavy use keys | Most plastics | Low cost keyboards, novelty caps |
How does the controller scan the matrix?
Why a matrix
Giving every key its own wire to the controller would need one input pin per key. A matrix shares wires. Worked example (illustrative): a 104 key full size layout can sit in a 6 row by 18 column matrix, which has 108 positions and needs 6 + 18 = 24 pins instead of 104. A 60 percent board with 61 keys fits in a 5 by 14 matrix, 70 positions on 19 pins. That saving is why every keyboard, from a membrane office board to a split ergonomic board, uses a matrix of some kind.
The scan loop
The QMK documentation describes the loop plainly. The firmware drives one column at a time to a logical 1 and reads all the rows at once. If a switch at that column is closed, the 1 passes through it to its row and the firmware sees that row go high. Repeat for every column, store the result as a bit map, compare it with the last scan, debounce the differences, and you know which keys went down or up. The loop runs continuously, many times per millisecond on a modern MCU.
Ghosting and why diodes fix it
Without diodes, current can take a detour. Hold three keys that form three corners of a rectangle in the matrix, and the scan reads the fourth corner as pressed too, because current flows backwards through the held switches. QMK's documentation calls this ghosting and shows that it happens only in specific combinations, but more often on bigger boards. A diode in series with each switch lets current flow only one way, so the detour is blocked and the firmware reads exactly the keys that are down. Membrane keyboards usually have no diodes, so their controllers detect impossible combinations and refuse to report them; the user sees this as a limit on how many keys work together.
From matrix position to key code
The firmware then looks up each matrix position in a keymap and turns it into a usage code from the USB HID Usage Tables. In HID Usage Tables 1.5 (26 January 2024), the Keyboard/Keypad page is page 0x07. On that page, usage 0x04 is "Keyboard a and A", usage 0x28 is "Keyboard Return (ENTER)", usage 0xE1 is "Keyboard LeftShift", and usage 0x01 is "Keyboard ErrorRollOver". The keyboard never sends letters. It sends positions on a standard page, and the operating system's layout setting decides that usage 0x04 means "a" on a US layout and something else on another.
How does a keyboard talk to the computer over USB HID?
Descriptors first
When a keyboard is plugged in, the host asks it for descriptors. The device descriptor names its vendor ID and product ID, the interface descriptor declares class 3 (HID), and a HID report descriptor describes, in a compact byte code, the exact layout of every report the device will send and receive. The USB HID 1.11 specification says one goal of the class was to be as compact as possible, and the Linux kernel's introduction to HID report descriptors shows how to read one from /sys/bus/hid/devices/.../report_descriptor and decode it with tools such as hid-tools.
The boot protocol and the 8 byte report
A BIOS or UEFI setup screen should not have to parse report descriptors, so the HID specification defines a fixed "boot protocol". A keyboard that sets interface subclass 1 (Boot Interface) and protocol 1 (Keyboard) promises to send this 8 byte input report when the host asks for boot protocol:
| Byte | Meaning |
|---|---|
| 0 | Modifier keys, one bit each: left Ctrl, left Shift, left Alt, left GUI, right Ctrl, right Shift, right Alt, right GUI |
| 1 | Reserved for OEM use; usually zero |
| 2 to 7 | Up to six key codes from the Keyboard/Keypad page |
It also defines a 1 byte output report the host sends back to light the Num Lock, Caps Lock, Scroll Lock, Compose and Kana LEDs. The specification says the keyboard must report a list of keys currently pressed, not make and break events, and that "Repeat Rate" and "Delay Before First Repeat" are implemented by the host. When the host's HID driver loads, it switches the keyboard from boot protocol to report protocol with a Set_Protocol request and from then on reads the reports the report descriptor describes.
Worked example: Shift plus A
Press left Shift and then A. The modifier byte sets bit 1 for left Shift, which is 0x02, and the first key code slot holds 0x04 for "a and A":
02 00 04 00 00 00 00 00 left Shift + a
00 00 00 00 00 00 00 00 all keys released
The host sees the transition from no keys to Shift plus 0x04 and, with a US layout, produces a capital A. If you hold the keys, the keyboard keeps reporting the same state; the host's repeat timer decides when to type a second A.
Rollover: 6KRO, ErrorRollOver and NKRO
The boot report has six key slots, so a boot protocol keyboard can report at most six ordinary keys plus any modifiers at once. HID 1.11 says the keyboard must report a "phantom state" by filling every array slot with the ErrorRollOver usage when more keys are pressed than the report can carry, and that it may do the same when it cannot tell which keys are really down, such as a ghosting combination on an undioded matrix. Worked example: hold seven letter keys and a compliant boot keyboard sends 00 00 01 01 01 01 01 01, telling the host that the set of keys is not reliable.
N key rollover (NKRO) avoids that limit by describing a different report in the report descriptor, typically a bit map with one bit per usage instead of six array slots. The open source QMK firmware exposes this as an NKRO_ENABLE build option and notes that its NKRO, mouse keys and media keys are combined onto one shared endpoint by default. A board offering NKRO usually still presents a boot compatible interface so it works in firmware setup screens.
Polling rate
USB keyboards send reports over an interrupt IN endpoint, and the endpoint descriptor's bInterval field asks the host to poll it at a fixed interval. The example descriptors in HID 1.11 use bInterval 0x0A, which asks for a poll every 10 ms. Keyboards advertised at 1,000 Hz ask for 1 ms, and some boards on faster USB connections ask for shorter intervals still. QMK lets a board set this with USB_POLLING_INTERVAL_MS. The polling interval is the upper bound on how long a ready report waits for the host; as the debounce example showed, the switch and the firmware usually add more.
What firmware runs on a keyboard?
Vendor firmware
Most keyboards run closed firmware written by the keyboard maker or by the maker of the controller chip's reference design. It includes the matrix scan, debounce, keymap, lighting effects, macro storage and, on wireless boards, a radio stack. A companion desktop application often talks to the keyboard over a vendor defined HID interface to change lighting and macros or to update firmware. That application is software you install with administrator rights, with its own dependencies and update channel.
Open source keyboard firmware
Enthusiast and many small batch keyboards run open source firmware. Two projects have extensive official documentation:
- QMK mainly targets wired keyboards on AVR and ARM microcontrollers, is licensed under the GPL (its repository lists GPL 2.0 licensing), and is built from a large shared repository of keyboard definitions. You set up a build environment with the
qmkcommand line tool, compile withqmk compileand flash withqmk flash. - ZMK is MIT licensed and built on the Zephyr real time operating system. Its documentation lists low latency Bluetooth LE, multi device BLE connectivity, USB and wireless split keyboards as supported features, and explicitly does not plan support for 8 bit AVR chips. ZMK's recommended setup is a personal "zmk-config" repository on GitHub, where GitHub Actions builds your firmware in the cloud and you download the resulting
.uf2or.hexfile.
That second detail matters for supply chain thinking. In June 2025 the ZMK documentation team asked users to pin their ZMK version, explaining that unpinned configurations build against the main branch and can pick up breaking changes. Pinning means changing revision: main to a release tag such as v0.2 in config/west.yml and changing the reusable workflow reference in .github/workflows/build.yml from @main to the same tag. In other words, keyboard firmware built this way is a dependency graph: your keymap, ZMK, Zephyr, hardware modules and a CI workflow, all fetched at build time.
Bootloaders: how new firmware gets in
A bootloader is a small program that runs before the main firmware and can write a new image to flash. QMK's flashing guide lists many, and they fall into a few families:
| Bootloader family | How you enter it | How you flash | Notes from the official docs |
|---|---|---|---|
| Chip vendor USB DFU on AVR | Bootloader keycode, reset button, or shorting reset to ground | dfu-programmer or QMK Toolbox | QMK says Atmel's DFU bootloader comes on all USB AVRs by default, with a couple of exceptions |
| Arduino style (Caterina) | Reset, often double tap | avrdude | Used by Arduino boards and clones |
| ROM DFU on STM32 and APM32 | Bootloader keycode, reset button, or bridging BOOT0 | dfu-util | QMK notes most USB capable STM32 parts have a factory bootloader that cannot be modified or deleted |
| UF2 mass storage (RP2040 and others) | Hold BOOTSEL while plugging in, double tap reset, or bootloader keycode | Copy a .uf2 file onto the drive that appears | Any application that can copy a file can flash it |
| Vendor proprietary | Vendor app or key combination | Vendor updater, sometimes over a HID interface | Behaviour defined only by the vendor |
A bootloader that ships in mask ROM cannot be bricked, which is convenient, but it also cannot be patched, and it will accept whatever image the protocol delivers unless the chip has its own secure boot feature turned on.
What the USB DFU standard does and does not promise
The USB Device Firmware Upgrade specification 1.1 (5 August 2004) defines four phases: enumeration, where the device advertises a DFU interface alongside its normal one; reconfiguration, where the host resets the device into DFU mode; transfer, where the host sends the image in blocks and polls status; and manifestation, where the host resets the device again and it runs the new firmware. It defines a file suffix with a CRC so a host can check a file is meant for that device, and status codes such as errFILE, for a file that "fails some vendor-specific verification test", and errVERIFY, for programmed memory that failed verification.
What it does not define is cryptographic authenticity. Whether an image must be signed, by whom, and whether the device refuses an older vulnerable version is up to the vendor. DFU also defines an optional upload direction (DFU_UPLOAD) whose stated purpose is to retrieve and archive a device's firmware, so a device that leaves upload enabled lets anyone with the cable read its firmware back. None of this makes DFU unsafe; it means that "supports DFU" tells you nothing about signed updates. Ask the vendor.
Firmware on the Linux side: fwupd and LVFS
On Linux, the fwupd daemon and the Linux Vendor Firmware Service (LVFS) give users one place to see device firmware versions and receive vendor uploaded updates. The LVFS describes itself as a secure portal where hardware vendors upload firmware in a standard .cab archive with metadata, used by major Linux distributions for clients such as fwupdmgr. Whether your keyboard appears there depends entirely on whether its maker publishes to the LVFS.
How do wireless keyboards pair?
Bluetooth LE: HID over GATT
Bluetooth LE keyboards follow the HID over GATT Profile (HOGP). The Bluetooth SIG describes it as defining how a Bluetooth LE device can support HID services over the LE stack using the Generic Attribute Profile. The HID Service carries the same report descriptor and reports as USB HID, wrapped in GATT characteristics, plus a Boot Keyboard Input Report characteristic for simple hosts.
Security is written into the profile. HOGP 1.0 says HID Devices shall bond and use LE Security Mode 1 with Security Level 2 or 3, all supported HID Service characteristics shall require that security, and the HID Host shall bond with the HID Device. When a bonded keyboard reconnects, the host starts encryption to check the bond is still valid, and if encryption fails the host must, after user interaction, pair again.
ZMK's own documentation is unusually frank about what that leaves. It says BLE connections are secured by an initial pairing and bonding process that sets up long term keys using Elliptic Curve Diffie Hellman, and that the only known weakness in that protocol is an active man in the middle attack during the initial pairing, which the Numeric Comparison association model can mitigate. ZMK describes its support for Numeric Comparison as experimental. The practical lesson for any BLE keyboard: pair it somewhere private, and treat an unexpected request to pair again as a reason to check before accepting.
ZMK also stores each bond in a "profile", so one keyboard can be bonded to several hosts and switched between them. Its documentation warns that bond key mismatches between profiles and hosts cause confusing behaviour, which is the most common reason a wireless keyboard "stops working" after an operating system reinstall: the host forgot the bond and the keyboard did not.
Proprietary 2.4 GHz dongles
Many wireless keyboards instead pair with a small USB receiver over a proprietary protocol in the 2.4 GHz band. In the United States, these radios typically operate under 47 CFR 15.247, which covers frequency hopping and digitally modulated intentional radiators in the 2400 to 2483.5 MHz band, or under the lower power rules for that band. Those rules govern power, bandwidth and interference. They say nothing about encryption, pairing or authentication; that is entirely the vendor's design.
The receiver is itself a USB device with a microcontroller, a radio and firmware. To the host it is a keyboard (often a keyboard and a mouse). To the radio side it is a receiver that decides which over the air packets to accept. If it accepts something it should not, the host has no way to tell, because the host only sees a HID keyboard sending reports.
What published research on dongles showed
On 24 February 2016, CERT/CC published Vulnerability Note VU#981271, titled "Multiple wireless keyboard/mouse devices use an unsafe proprietary wireless protocol". It classified the issue as CWE-311, missing encryption of sensitive data, and said that several wireless input devices using proprietary 2.4 GHz protocols lacked proper encryption, so someone within radio range, typically a few metres in a home, could inject keystrokes, read keystroke data, or cause the victim's receiver to pair with a new input device. CERT/CC noted the issue did not affect Bluetooth devices, recorded that at least one affected vendor released updated receiver firmware, and advised users of other models to weigh their own threat model until updates arrived.
The mechanism, in concept: some receivers accepted unencrypted packets formatted as keystrokes even when the paired keyboard normally encrypted its traffic, and some would accept a new device pairing without the user starting it. The fix was receiver firmware that rejects unencrypted keystroke packets and only pairs when the user asks. The lessons last longer than the specific products:
- A dongle is a computer with firmware, and its firmware needs updates like anything else.
- Pairing must be a deliberate, user initiated act on both sides.
- Encryption that the receiver does not enforce is not encryption.
- Updating the keyboard alone may not help; the receiver is often the component that needs the patch.
Comparison: wired, Bluetooth LE and 2.4 GHz dongle
| Property | Wired USB | Bluetooth LE (HOGP) | Proprietary 2.4 GHz dongle |
|---|---|---|---|
| Who defines the link | USB-IF HID class | Bluetooth SIG HOGP and Core | The vendor |
| Encryption | None needed on the cable | Required by HOGP (Security Mode 1, Level 2 or 3) | Vendor defined; varies by product |
| Pairing | None; plug in | Bonding with long term keys | Vendor defined; often factory paired |
| Over the air exposure | None | Pairing window is the weak point | Depends entirely on receiver firmware |
| Firmware to patch | Keyboard | Keyboard, plus the host's Bluetooth stack | Keyboard and receiver |
| Works in BIOS or UEFI setup | Yes, via boot protocol | Often not until the OS loads | Usually yes, receiver presents a USB HID device |
| Fits a high security area | Easiest to approve | Possible with a pairing procedure | Only with vendor documentation of encryption and signed updates |
What are keystroke injection devices, and why do hosts trust any USB keyboard?
A keystroke injection device is any gadget that presents itself to a computer as a keyboard and then types something its owner chose in advance. Physically it can look like a flash drive, a cable, a charging gadget or a real keyboard. The concept is simple, and because this post does not give attack instructions we will leave it there: the device enumerates as a HID keyboard and sends ordinary key reports.
Hosts trust it for two structural reasons.
First, USB HID has no authentication. Every field in the device descriptor and report descriptor is the device's own claim. A vendor ID and product ID identify a product line, not a genuine unit, and nothing in the HID class asks the device to prove anything. The Linux kernel's USB authorization documentation says it directly: "By default, all USB devices are authorized." It adds that just checking whether the class, type and protocol match something is the worst security verification you can make, and that real assurance needs cryptography.
Second, keyboards are how people log in and recover systems. An operating system that refused new keyboards would lock users out of their own machines after a hardware fault, so every mainstream desktop accepts them by default.
The 2014 Black Hat USA briefing "BadUSB, On Accessories that Turn Evil" showed a related point: the controller firmware in ordinary USB devices can be reprogrammed so the device spoofs other device types in order to take control of a computer. For keyboards themselves, the same idea applies to replaced firmware: a keyboard whose bootloader accepts unsigned images can be turned into a device that types on its own.
The defences are layered and mostly organisational. Hosts can allow list USB devices by class, vendor, product, serial and port, so a "flash drive" that also exposes a keyboard interface is rejected. NIST SP 800-53 Rev. 5 control SC-41, Port and I/O Device Access, has organisations disable or remove ports on defined systems, and notes that physically disabling or removing them is the stronger action. MP-7, Media Use, restricts types of media and prohibits portable storage with no identifiable owner, while CM-8, System Component Inventory, and SR-11, Component Authenticity, cover knowing what is attached and keeping counterfeits out. Short screen lock timeouts help too, since many injection scenarios need an unlocked session.
How do you check a keyboard's firmware and update it safely?
The steps below are for Linux, with macOS and Windows equivalents where they exist. Read the warnings before the flashing steps: writing the wrong image to the wrong device can leave a keyboard unusable until you reach its bootloader by hand.
1. Identify the keyboard and its interfaces
# List USB devices with vendor and product IDs
lsusb
# Show every interface the keyboard exposes (replace with your IDs)
lsusb -v -d 1234:5678 2>/dev/null | grep -E "bcdDevice|iProduct|bInterfaceClass|bInterfaceSubClass|bInterfaceProtocol|bInterval"
bcdDevice is the device release number, which many vendors tie to firmware version. Count the interfaces: a plain keyboard usually has one or two HID interfaces. Extra interfaces (mass storage, network, a vendor specific class) deserve a question to the vendor.
On macOS, system_profiler SPUSBDataType lists USB devices and system_profiler SPBluetoothDataType lists paired Bluetooth devices. On Windows, Get-PnpDevice -Class Keyboard in PowerShell lists keyboard devices, and Device Manager shows the hardware IDs.
2. Read the HID report descriptor
# Find the HID device entries for the keyboard
ls /sys/bus/hid/devices/
# Dump the report descriptor (read only)
sudo hexdump -C /sys/bus/hid/devices/0003:1234:5678.0001/report_descriptor
The Linux kernel's HID introduction shows exactly this, and points to tools that decode the bytes into readable usages. A descriptor that defines keyboard usages on an interface you did not expect, or several keyboard collections, is worth understanding before you approve the device.
3. Check for vendor firmware through fwupd
fwupdmgr get-devices # versions fwupd can see
fwupdmgr refresh # fetch LVFS metadata
fwupdmgr get-updates # updates published for your devices
If the keyboard or its receiver is listed, fwupd shows the current version and any update the vendor has published to the LVFS. If it is not listed, the vendor's own updater is the source of truth; download it only from the vendor's site, and record the version before and after.
4. For open source firmware, pin and build reproducibly
For a QMK board, record the commit you build from:
qmk setup # first time only
cd ~/qmk_firmware && git rev-parse HEAD
qmk compile -kb <keyboard> -km <keymap>
sha256sum *.hex *.bin *.uf2 2>/dev/null
For ZMK, pin the version in your zmk-config repository as the ZMK documentation describes:
# config/west.yml
manifest:
remotes:
- name: zmkfirmware
url-base: https://github.com/zmkfirmware
projects:
- name: zmk
remote: zmkfirmware
revision: v0.3 # a release tag, not main
import: app/west.yml
self:
path: config
# .github/workflows/build.yml
name: Build ZMK firmware
on: [push, pull_request, workflow_dispatch]
jobs:
build:
uses: zmkfirmware/zmk/.github/workflows/build-user-config.yml@v0.3
Use the release tag current when you read this; the ZMK documentation listed v0.3 as the latest release when we checked. Keep the downloaded build artifact and its hash with the commit that produced it.
5. Before flashing: the device check
Warning. Flashing erases the keyboard's current firmware. Disconnect every other device that uses the same bootloader type (another keyboard, a development board) so the tool cannot pick the wrong one, keep a working second keyboard attached, and confirm the target before you write.
# Put the keyboard in its bootloader, then confirm exactly one target appears
lsusb | grep -i -E "dfu|bootloader"
dfu-util -l # for DFU bootloaders: must list exactly one device
lsblk -o NAME,LABEL,SIZE,MODEL # for UF2: confirm the new drive's label and size
If more than one candidate appears, or the label and size do not match your board's documentation, stop.
6. Flash with the documented tool
Warning. This writes to the device. Run it only after step 5 shows one matching target.
# QMK, any supported bootloader
qmk flash -kb <keyboard> -km <keymap>
# STM32 ROM DFU example, as given in the QMK flashing docs
dfu-util -a 0 -d 0483:DF11 -s 0x8000000:leave -D firmware.bin
# UF2 bootloader: copy the file to the drive that appeared in step 5
cp firmware.uf2 /media/$USER/<BOOTLOADER_LABEL>/
7. Verify
Unplug and replug. Check lsusb -v shows the expected bcdDevice or version string, test every key with a key tester or evtest, and for wireless boards remove and recreate the Bluetooth bond so host and keyboard agree on keys.
8. Lock down which HID devices a Linux host accepts
The kernel authorization feature lets a host hold new devices unconfigured:
# Inspect, do not change, the current default for each USB bus
cat /sys/bus/usb/devices/usb*/authorized_default
The kernel documentation explains that writing 0 deauthorizes new devices by default and that writing 2 authorizes only devices on internal ports. Do not set 0 on a remote machine whose only keyboard is USB unless you have another way in. Most teams use a policy daemon instead. The open source USBGuard project builds on this kernel feature, and its rule language documentation includes a policy that allows flash drives but rejects any that also present a HID keyboard, communications or wireless interface:
allow with-interface equals { 08:*:* }
reject with-interface all-of { 08:*:* 03:00:* }
reject with-interface all-of { 08:*:* 03:01:* }
reject with-interface all-of { 08:*:* e0:*:* }
reject with-interface all-of { 08:*:* 02:*:* }
USBGuard's own documentation notes that block listing is the wrong long term approach and that an allow list is stronger. Generate a starting policy from the devices currently attached, review it, then enforce it.
What should an organisation require of keyboards?
| Requirement | Why | How to check |
|---|---|---|
| Wired by default in sensitive areas | Removes the radio attack surface entirely | Procurement standard |
| Bluetooth LE only, no proprietary dongle, where wireless is needed | HOGP mandates bonding and encryption | Vendor data sheet names HOGP; pair in a controlled place |
| Documented encryption for any 2.4 GHz receiver | Encryption is vendor defined | Written vendor statement; update history for receiver firmware |
| Signed firmware updates and rollback protection | DFU alone does not require them | Vendor security documentation; ask whether unsigned images are refused |
| A published update channel | Lets you patch the receiver and keyboard | Vendor support page or LVFS listing |
| No unexpected USB interfaces | Extra interfaces widen what the device can do | lsusb -v at intake; compare against an approved list |
| Asset tagging and inventory | NIST CM-8 component inventory | Record vendor ID, product ID, serial and firmware version |
| Host device control | SC-41 port control and allow listing | Endpoint policy; USBGuard or equivalent on Linux |
| Companion software reviewed like any app | Configurator apps run with high privileges | Software approval process, dependency review |
| Supplier authenticity | SR-11 component authenticity | Buy through authorised channels; check packaging and IDs |
Common mistakes
- Treating a keyboard as passive hardware. It runs firmware, often has a bootloader that accepts new images, and a wireless receiver is a separate computer with its own firmware.
- Patching the keyboard but not the receiver. Dongle research showed the receiver is often where the fix lives.
- Assuming vendor ID and product ID prove identity. They are claims made by the device. Allow lists based on them reduce accidents, not determined attackers; combine them with physical controls.
- Accepting a surprise Bluetooth pairing request. HOGP's weak point is the pairing moment. Re-pair only when you started it.
- Building open source firmware from an unpinned branch. ZMK's own maintainers recommend pinning to a release tag; the same goes for a QMK commit.
- Flashing with several bootloader devices attached. The tool may write to the wrong one. Confirm exactly one target first.
- Relying on block lists in device control. An allow list of known good devices and interface sets is the stronger pattern.
- Assuming "1,000 Hz" means 1 ms end to end. Debounce and scan time usually add more than the poll interval.
FAQ
What is inside a mechanical keyboard?
Keycaps, switches, often a plate, stabilisers for long keys, a PCB that wires the switches into a row and column matrix with one diode per switch, a microcontroller running firmware, a USB connector or a battery and radio, and the case.
How does a keyboard send a key press to the computer?
The controller scans the matrix, debounces the result, looks up each pressed position in its keymap and sends a USB HID report listing the usage codes of keys that are down. The host compares each report with the last one and turns changes into key events using the selected layout.
What is the difference between 6KRO and NKRO?
6KRO comes from the USB HID boot keyboard report, which has six key slots plus a modifier byte, so six ordinary keys can be reported at once. NKRO uses a different report layout, usually a bit map, so every key can be reported simultaneously. Most NKRO boards still offer a boot compatible mode for firmware setup screens.
Why do mechanical keyboards have diodes?
Without a diode in series with each switch, holding certain three key combinations makes a fourth, unpressed key appear pressed, an effect called ghosting. Diodes let current flow one way only, so the controller reads exactly the keys that are down.
Are Hall effect keyboards more reliable than mechanical ones?
They remove the metal contacts that bounce and wear, so they need less debouncing and can adjust actuation in firmware. They still have springs, housings and electronics that wear, and they depend on calibration. Reliability depends on the specific design and its testing.
Are Bluetooth keyboards secure?
Bluetooth LE keyboards that follow the HID over GATT Profile must bond and use an encrypted link. The main exposure is the pairing moment, when an attacker nearby could try to sit in the middle. Pair in a private place, use authenticated pairing where offered, and keep the keyboard and host Bluetooth stack updated.
Are wireless keyboards with USB dongles safe to use?
It depends on the product. Proprietary 2.4 GHz protocols are defined by each vendor, and in February 2016 CERT/CC warned that several lacked proper encryption. Choose models whose vendors document encryption and publish receiver firmware updates, and update the receiver, not just the keyboard.
How do I check my keyboard's firmware version?
On Linux run lsusb -v and read bcdDevice, then fwupdmgr get-devices to see whether fwupd recognises it. On macOS use system_profiler SPUSBDataType. Many vendors also show the version in their configuration app. For open source firmware, record the commit or release tag you built.
Can a keyboard get a virus?
A keyboard whose bootloader accepts unsigned firmware can be reprogrammed to behave differently, including typing on its own, and research presented at Black Hat USA in 2014 showed the same idea for USB controller firmware in general. That requires replacing its firmware, usually with physical access. Buying from authorised channels, preferring signed updates and controlling which USB devices hosts accept all reduce the risk.
What is a keyboard bootloader?
A small program that runs before the main firmware and can write a new firmware image to flash. Common types on open source boards are USB DFU, Arduino style serial bootloaders and UF2, which appears as a drive you copy a file onto. Some live in read only memory and cannot be erased.
Where Safeguard fits, honestly
Safeguard does not make, test or analyse keyboards. It does not scan keyboard or receiver firmware, verify firmware signatures, generate a hardware bill of materials, manage devices or enforce USB policy on endpoints, and its models are single purpose security models for software. The fit is narrower and it sits in the software around the keyboard. Configurator and macro apps your team builds or packages, internal device inventory tools that collect lsusb and fwupd output, and build tooling for custom keyboards in your repositories all pull open source dependencies through ordinary package managers. Safeguard scans repositories, container images and SBOM files for known vulnerable components, shows which projects carry a given component and version, and can open fix pull requests when a fixed version exists, with autonomous remediation switched off by default.
A keyboard's firmware is built from open source projects, real time operating systems and CI workflows fetched at build time, and every laptop rebuild pulls its companion apps and their libraries again. The fit is indirect, because Safeguard does not touch the keyboard hardware or its firmware image, but the software you write and package to configure, inventory and update peripherals is part of your software supply chain like everything else.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
The first demo is a real Safeguard CLI session asked to fix a lodash CVE: it reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, and pushes nothing. The same flow fits a keyboard configurator app or a device inventory dashboard your team maintains in a JavaScript repository.
Click through it at your own pace, or open it full screen.
The second demo sets up the Safeguard runner on your own machine, approves it with its device code and scans from the terminal. That suits teams who keep peripheral tooling, firmware build scripts or workstation images in repositories they prefer to scan locally.
Click through it at your own pace, or open it full screen.
The third demo is a real Android session: send work to a computer running the CLI and approve each command on the phone with Allow once, Allow for turn or Deny. An engineer away from a desk can approve a dependency fix in a fleet tooling repository without anything running unattended.
Click through it at your own pace, or open it full screen.
To try it on your own repositories, download Safeguard and follow the CLI documentation.
Quick check
Why can a boot protocol keyboard report only six ordinary keys at once?
The USB HID 1.11 boot keyboard report is 8 bytes: one modifier byte, one reserved byte and six key code slots. When more than six non modifier keys are down, the keyboard fills every slot with the ErrorRollOver usage instead.
Does a keyboard that supports USB DFU have signed firmware updates?
Not necessarily. The USB DFU 1.1 specification defines how an image is transferred and checked for the right device, but leaves any authenticity check to the vendor. Ask the vendor whether unsigned or older images are refused.
Sources
- USB-IF, Device Class Definition for HID 1.11 (document page)
- USB-IF, Device Class Definition for Human Interface Devices (HID) 1.11 (PDF)
- USB-IF, HID Usage Tables 1.5 (PDF)
- USB-IF, HID information page
- USB-IF, Device Class Specification for Device Firmware Upgrade 1.1 (PDF)
- Bluetooth SIG, HID over GATT Profile 1.0 (specification page)
- Bluetooth SIG, HID over GATT Profile 1.0 (HTML specification)
- Linux kernel documentation, Introduction to HID report descriptors
- Linux kernel documentation, Authorizing (or not) your USB devices to connect to the system
- QMK Firmware, How a Keyboard Matrix Works
- QMK Firmware, Debounce API
- QMK Firmware, Flashing Instructions and Bootloader Information
- QMK Firmware, Flashing Your Keyboard (tutorial)
- QMK Firmware, Configuring QMK (config options)
- QMK Firmware, GitHub repository
- ZMK Firmware, Introduction to ZMK
- ZMK Firmware, Bluetooth
- ZMK Firmware, Installing ZMK (user setup)
- ZMK Firmware blog, Pin your ZMK version (20 June 2025)
- CERT/CC, Vulnerability Note VU#981271 (24 February 2016)
- Black Hat USA 2014 briefings (archived), BadUSB, On Accessories that Turn Evil
- CISA, Using Caution with USB Drives (1 February 2021)
- NIST, SP 800-53 Rev. 5 catalog in OSCAL (controls SC-41, MP-7, CM-8, SR-11)
- eCFR, 47 CFR 15.247, Operation within the bands 902 to 928 MHz, 2400 to 2483.5 MHz and 5725 to 5850 MHz
- USBGuard project, home
- USBGuard project, Rule Language
- LVFS, Linux Vendor Firmware Service home
- LVFS documentation, Introduction
Last reviewed: 23 October 2026.