Skip to content

fix(corewlan): detect redaction from the data, not the status - #13

Merged
krisarmstrong merged 1 commit into
mainfrom
fix/corewlan-detect-redaction
Aug 24, 2026
Merged

fix(corewlan): detect redaction from the data, not the status#13
krisarmstrong merged 1 commit into
mainfrom
fix/corewlan-detect-redaction

Conversation

@krisarmstrong

Copy link
Copy Markdown
Contributor

Why

DecodeScan trusted the authorization status. That is not sufficient, and the failure is silent.

CoreWLAN redacts according to the calling process's own client identity. A bundled executable launched directly — rather than through LaunchServices — is a different CoreWLAN client from its bundle. So the manager can truthfully report that the bundle holds the grant, while the scan it hands back is stripped.

Observed on macOS 27.0 running Trellis's capture binary directly out of its signed, entitled, authorized bundle:

$ plutil -p /var/db/locationd/clients.plist | grep -A5 trellis.capture
"BundleId" => "net.mustardseed.trellis.capture"
"Authorized" => true

$ ./Trellis Capture.app/Contents/MacOS/trellis-capture
[{"ssid":"","bssid":"","signal":-47,"channel":40,"frequency":5200,"security":"WPA3",...},
 {"ssid":"","bssid":"","signal":-75,"channel":11,"frequency":2462,"security":"WPA3",...},
 ...13 networks, not one identifier among them]

No error. Correct RSSI, correct channels, correct security — and nothing nameable. For a survey product that is worse than a failure: it records a walk of nameless BSSIDs that looks exactly like data.

Fix

DecodeScan also returns ErrLocationDenied when a scan found networks and named none of them. A real observation always carries a BSSID, so that state is unambiguous.

An empty airspace stays a successful empty scan — there is nothing to strip, so len == 0 is not redaction.

Tests

Two added:

  • authorized status, every identifier stripped → ErrLocationDenied
  • authorized status, zero networks → success, empty

gofmt · go vet · golangci-lint 0 issues · go test -race · darwin and linux build.

Consumers

Both seed and trellis get this for free on the next bump; neither needs a code change. Seed's helper is launched by launchd from a plist that names the inner binary, which is exactly the shape that can hit this.

A scan could return with every SSID and BSSID stripped and still be reported as
success, because the check was the authorization status alone.

CoreWLAN redacts according to the calling process's own client identity, and a
bundled executable launched directly rather than through LaunchServices is a
different client from its bundle. So the manager can truthfully report that the
bundle holds the grant while the scan it hands back is stripped. Observed on
macOS 27.0: status authorized, thirteen networks, not one identifier among them.

DecodeScan now also treats a scan that found networks and named none of them as
ErrLocationDenied. A real observation always carries a BSSID, so that state is
unambiguous. An empty airspace stays a successful empty scan — there is nothing
to strip.

This is the failure the package exists to prevent: silently recording signal
strengths against nameless BSSIDs, which for a survey looks exactly like data.
@krisarmstrong
krisarmstrong merged commit 5cb024b into main Aug 24, 2026
5 checks passed
@krisarmstrong
krisarmstrong deleted the fix/corewlan-detect-redaction branch August 24, 2026 23:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant