v0.4.7: ephemeral port rotation is churn (found by dogfooding, hour one) - #5
Merged
Conversation
…the overlap Found by dogfooding, one hour into the three-day trial, on a real Mac. Six adversarial review rounds did not find it, because it is not a logic error you can see by reading — it needs a machine where Apple's `rapportd` actually rotates its ports. Measured on the trial machine: rapportd 57905,65426,65427 -> 57905,65428,65429 (keeps one, rotates two) v0.4.6 asked "do the port sets overlap?" to decide churn. They do overlap here, so it called this a real signal and reported it at ORANGE — which crosses the --notify threshold. On a normal Mac that is a desktop notification every few hours forever, and a digest that cries wolf every few hours is one nobody reads. That failure mode is worse for this tool than most missed detections, because it disables the reader. Churn is now a balanced ROTATION entirely inside the ephemeral range (>=32768), decided on what CHANGED rather than on set overlap. A net GAIN is never suppressed whatever the port number — including ephemeral ports, since malware binds those too (`sshd 22 -> 22,49999` still reports). The three real rotations observed on the trial machine are now test fixtures, and the five gain/rebind cases from the v0.4.6 churn fix still report. Mutations both caught: reverting to the overlap test, and suppressing net gains. Suite 658 -> 667. Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found by running the tool on a real Mac, one hour into a three-day trial — not by any of the six adversarial review rounds. It isn't a logic error you can see by reading; it needs a machine where Apple's
rapportdactually rotates its ports.Measured on the trial machine
v0.4.6 decided churn by asking "do the port sets overlap?" They do here — so it treated a routine rotation as a real signal and reported it at ORANGE, which crosses the
--notifythreshold.On a normal Mac that's a desktop notification every few hours, forever. For this tool that failure mode is worse than most missed detections, because it disables the reader: a digest that cries wolf every few hours is one nobody reads.
The fix
Churn is a balanced rotation entirely inside the ephemeral range, judged on what changed rather than on set overlap:
A net gain is never suppressed, whatever the port number — including ephemeral ones, because malware binds those too.
57905,65426,65427 → 57905,65428,65429(real)59858,65469,65470 → 59858,65471,65472(real)8080 → 444449152 → 49157,4444(backdoor under a churny name)22 → 22,444422 → 22,49999(net gain, ephemeral)22,80 → 80(stopped listening)The three real rotations are now regression fixtures, alongside the five gain/rebind cases from the v0.4.6 churn fix. Both mutations caught: reverting to the overlap test, and suppressing net gains.
Suite 658 → 667.
Why this matters beyond the bug
The v0.4.6 rule was itself a fix for the opposite failure — "no overlap ⇒ churn" was silently dropping
8080 → 4444. Both directions of that rule were wrong, and each was only visible from a different vantage point: the missed detection from adversarial review, the false alarm from actually living with the output.🤖 Generated with Claude Code