Skip to content

A strap serial hidden in a hex payload walks past every redaction rule #1833

Open

Description

@ryanbr

The gap

redactStrapLogPii scrubs identifiers written as text:

private val PII_WHOOP_SERIAL_RE = Regex("WHOOP (\\d[0-9A-Za-z]{5,})")

It cannot see an identifier that arrives as hex, because it is reading hex digits rather than the
ASCII those bytes decode to.

That is not theoretical. On a WHOOP 5/MG, event 0x6D(109) carries the strap serial as plain ASCII
inside its payload:

payload=142e1c0001d36e3d1c12a35742423541503035333938353 20000
        \x14.\x1c\x00\x01\xd3n=\x1c\x12\xa3WBB5AP0539852\x00\x00
                                           ^^^^^^^^^^^^^ serial

Any diagnostic that dumps that payload puts the serial into the strap log — the file people are asked to
attach to a public issue. The MAC rule works (device=FD:••:••:••:••:4A in a real capture), so the log
looks redacted while an identifier passes through in a different encoding.

Where this already applies

The fix taken

Decode each payload=/frame= hex run, find printable ASCII stretches, and mask the bytes of any run
shaped like a serial — leaving the rest of the dump intact. Blanket-truncating the payload would defeat
the reason these dumps exist: the payload is exactly where an undocumented field would be found.

Landed on Android with the event census. The Apple twin is still open — LiveState.redactPii needs
the same treatment before another hex-dumping diagnostic is added there.

Worth noting

The serial in the example above is real, and it reached a public PR description through exactly this
route before anyone noticed. The redaction is not optional decoration; it is the thing that makes "please
attach your strap log" a safe request.

Activity

  1. Zebsi235 commented on Sep 6, 2026

    @Zebsi235

    One small thing I noticed while checking my own PRs for leftover identifiers, for your call: the doc comment on PII_WHOOP_SERIAL_IN_HEX_RE (or its neighbour — the /** A WHOOP serial as it appears in a payload … (e.g. WBB5AP0539852). */ line in WhoopBleClient.kt) uses the serial from my #1825 capture as its worked example. It is the live one from my strap.

    No harm done and I'm not asking for anything — a serial in a regex comment is a long way from a strap log. Just flagging it in case you'd rather the example be an obviously synthetic one (WBB5AP0000001 is what I used in the fixtures), since this is the code that exists to keep them out.

  2. evoveotech commented on Sep 10, 2026

    @evoveotech

    Verified fixed: Hex payload serial redaction is implemented on both platforms (Swift: Strand/BLE/FrameRouter.swift lines 339-341, Kotlin: WhoopBleClient.kt lines 1649, 1693, 1715) with tests (PiiRedactionTests.swift, HexPayloadRedactionTests.swift, PiiRedactionTest.kt).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions