device_digest is not unique across boards, weakening the USB provisioning anti-swap guard
Repo: ruvnet/RuView (firmware) · Severity: Medium-High · Measured: 2026-09-14, three ESP32-C6 boards on 0.8.12
Symptom
Two physically distinct boards report the same device_digest over RUVIEW_HELLO_V1:
node 11 device_digest=062009cef304369d
node 12 device_digest=062009cef304369d <-- identical
node 13 device_digest=e1303fbd5cd4cebd
Read in one pass across three ports, each nonce-matched, stable across reboots and across a
firmware reflash. Confirmed distinct hardware — esptool reports different efuse base MACs
for all three.
Not duplicate efuses
The firmware computes SHA-256("ruview-device-v1" || esp_efuse_mac_get_default())[0..8].
With distinct base MACs the digests cannot collide, so this was checked directly. Brute
force over the documented formula and every plausible variant — domain with and without the
NUL, raw / reversed / lowercase-hex / uppercase-hex / colon-separated MAC, 6-byte base and
8-byte extended MAC, prefix and suffix ordering — reproduces none of the three observed
digests, including the unique one.
So the shipped digest is not a function of the MAC in the way the source describes, and it
is not the all-zeros failure path either: the firmware believes it succeeded. It is silently
wrong rather than failing closed.
Impact
deviceDigest is the anti-swap guard in Mac USB provisioning
(RuViewNodeOnboardingModule.swift:119):
let attempt = try hello(on: descriptor, path: portPath, ...)
guard let hello = attempt.node, hello.deviceDigest == expectedDeviceDigest else {
throw RuViewNodeOnboardingError.identityMismatch
}
It re-runs HELLO before writing NVS to confirm the board is the one the operator selected.
With a colliding digest that guard cannot distinguish those two boards, so it degrades from
"verified identity" to "verified chip family". Serial paths do re-enumerate in practice —
observed during flashing — so a mix-up is reachable, and would write the wrong node ID to
the wrong board.
Detection is unaffected: the device list keys on serial path, so all boards appear
correctly.
Caveat on attribution
release_bins/c6-onboarding/esp32-csi-node.bin is a tracked binary blob, so it cannot be
proven that the serial_onboarding.c in the tree is the source that built it. The behaviour
is measured and reproducible; the cause needs a from-source rebuild to pin down.
device_digestis not unique across boards, weakening the USB provisioning anti-swap guardRepo: ruvnet/RuView (firmware) · Severity: Medium-High · Measured: 2026-09-14, three ESP32-C6 boards on 0.8.12
Symptom
Two physically distinct boards report the same
device_digestoverRUVIEW_HELLO_V1:Read in one pass across three ports, each nonce-matched, stable across reboots and across a
firmware reflash. Confirmed distinct hardware — esptool reports different efuse base MACs
for all three.
Not duplicate efuses
The firmware computes
SHA-256("ruview-device-v1" || esp_efuse_mac_get_default())[0..8].With distinct base MACs the digests cannot collide, so this was checked directly. Brute
force over the documented formula and every plausible variant — domain with and without the
NUL, raw / reversed / lowercase-hex / uppercase-hex / colon-separated MAC, 6-byte base and
8-byte extended MAC, prefix and suffix ordering — reproduces none of the three observed
digests, including the unique one.
So the shipped digest is not a function of the MAC in the way the source describes, and it
is not the all-zeros failure path either: the firmware believes it succeeded. It is silently
wrong rather than failing closed.
Impact
deviceDigestis the anti-swap guard in Mac USB provisioning(
RuViewNodeOnboardingModule.swift:119):It re-runs HELLO before writing NVS to confirm the board is the one the operator selected.
With a colliding digest that guard cannot distinguish those two boards, so it degrades from
"verified identity" to "verified chip family". Serial paths do re-enumerate in practice —
observed during flashing — so a mix-up is reachable, and would write the wrong node ID to
the wrong board.
Detection is unaffected: the device list keys on serial path, so all boards appear
correctly.
Caveat on attribution
release_bins/c6-onboarding/esp32-csi-node.binis a tracked binary blob, so it cannot beproven that the
serial_onboarding.cin the tree is the source that built it. The behaviouris measured and reproducible; the cause needs a from-source rebuild to pin down.