Skip to content

v0.4.7: ephemeral port rotation is churn (found by dogfooding, hour one) - #5

Merged
deva0x merged 1 commit into
mainfrom
fix/v0.4.7-trial-noise
Jul 25, 2026
Merged

v0.4.7: ephemeral port rotation is churn (found by dogfooding, hour one)#5
deva0x merged 1 commit into
mainfrom
fix/v0.4.7-trial-noise

Conversation

@deva0x

@deva0x deva0x commented Jul 25, 2026

Copy link
Copy Markdown
Owner

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 rapportd actually rotates its ports.

Measured on the trial machine

rapportd  57905,65426,65427  →  57905,65428,65429     (keeps one port, rotates two)
          overlap=[57905]  added=[65428,65429]  removed=[65426,65427]
          every port ephemeral (≥32768)

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 --notify threshold.

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:

if added_ports and removed_ports and _eph(added_ports) and _eph(removed_ports):
    continue        # churn

A net gain is never suppressed, whatever the port number — including ephemeral ones, because malware binds those too.

case verdict
57905,65426,65427 → 57905,65428,65429 (real) suppress
59858,65469,65470 → 59858,65471,65472 (real) suppress
8080 → 4444 report
49152 → 49157,4444 (backdoor under a churny name) report
22 → 22,4444 report
22 → 22,49999 (net gain, ephemeral) report
22,80 → 80 (stopped listening) report

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

…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>
@deva0x
deva0x merged commit 99da774 into main Jul 25, 2026
6 checks passed
@deva0x
deva0x deleted the fix/v0.4.7-trial-noise branch July 25, 2026 12:13
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