← All write-ups
October 6, 2026CRITICALSANITIZED CLIENT FINDING

Open JTAG and privileged control commands on a charging station

2026 · Client C · Energy, EV charging & monitoring

Summary

The device exposed a debug programming path while privileged protocol commands did not require a robust authentication mechanism. The web control plane also relied on predictable defaults and cleartext transport.

Technical workflow

The hardware phase documented exposed interfaces and firmware metadata without publishing reprogramming commands or device keys:

lsusb
strings -n 8 fixtures/device-recovery.bin | rg -i 'jtag|uart|debug|default|recovery'
sha256sum fixtures/device-recovery.bin

Protocol checks used a synthetic session and a harmless read-only status request. The server-side command gate should bind every privileged action to an authenticated device session and a freshness value:

import hmac

def verify_command(mac: bytes, message: bytes, session_key: bytes) -> bool:
    expected = hmac.digest(session_key, message, "sha256")
    return hmac.compare_digest(expected, mac)

def accept_nonce(nonce: str, seen: set[str]) -> None:
    if nonce in seen:
        raise ValueError("replayed command")
    seen.add(nonce)

In production, keep replay state durable and bind the message to device identity, command, parameters and expiry. Debug lockdown, unique credentials and authenticated encryption must be verified on the physical sample, not only in source configuration.

Defensive lessons

Expected result: debug access is disabled or authenticated, default credentials are rejected, cleartext management is unavailable and a replayed privileged command is denied.

This is a sanitized technical summary; device-specific commands and keys are omitted.