Skip to content

fix(helper)!: check ports 80/443 as root and drop kernel-table inspection - #409

Merged
clvsh merged 4 commits into
feat/loopback-port-probefrom
feat/root-low-port-inspection
Oct 8, 2026
Merged

clvsh merged 4 commits into
feat/loopback-port-probefrom
feat/root-low-port-inspection

Conversation

@clvsh

@clvsh clvsh commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

On macOS 27, ad-hoc signing anywhere in PV's ancestry can filter the TCP kernel table to PV's own sockets. The old 80/443 check could then report no conflict and redirect traffic away from another server. Issue #402's claim that production is unaffected was incorrect: the installed CLI is affected too.

The privileged helper now decides low-port availability with the shared bind probe as root. ports:install checks before preparing files or returning an already-current result. PfApply checks again before changing PF. Missing process information never makes a port free. A bounded lsof command supplies names and PIDs, with at most eight reported listeners per port; its errors stop the operation. Messages list those listeners without claiming which one caused the IPv4 bind failure, because lsof uses the same wildcard notation for IPv6-only and dual-stack listeners.

This bumps the helper to 2.0.0 and protocol 2, adds the fixed LowPortInspect request, and removes unused PfReload and the kernel-table listener API. The daemon never calls the helper. Correctness does not depend on signing identity or ancestry. The application version stays unchanged. Installation and rollback wait within the existing five-second budget for launchd's helper socket; authentication and invalid responses fail immediately.

Tests cover field parsing and diagnostic limits, a held high port alongside a free port, protocol round trips and removed-operation rejection, CLI conflicts before file writes and on a repeated install, setup retaining apply-time errors, and delayed/missing/invalid helper sockets. The root acceptance test starts a separate native holder for each of ports 80 and 443, checks its PID through LowPortInspect, exercises the actual PfApply guard, verifies unchanged PF state, and confirms the ports are free after cleanup.

CI runs that root test in every macOS lane. Cargo builds as the regular CI user; sudo runs only the exact verified test executable. Fixture readiness, system commands, and the CI step are bounded. The wider privileged RC workflow remains a follow-up. #403 adds the macOS 27 lane after this fix.

Validation: formatting, workspace Clippy with warnings denied, cargo-shear, and the full macOS 27 CI-profile suite pass: 1,610 normal tests passed. The earlier privileged installation and Python-server check also passed on this Mac: helper 2.0.0/protocol 2 installed, actual PfApply and the CLI refused the root server by PID, and ports:install succeeded after it stopped. The combined stack passed CI on macOS 14, 15, 26, and 27, including the separate-process root acceptance test in every macOS lane. Linux, Windows, benchmark checks, and automated reviews also passed in that run: https://github.com/prvious/pv/actions/runs/37825708765.

Based on #408. Closes #402.

@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: QUIET
  • Plan: Advanced
  • Run ID: 9a7c3720-06b4-4f52-ae41-07267002b786
📥 Commits

Reviewing files that changed from the base of the PR and between 4771790 and b64bd7a.

⛔ Files ignored due to path filters (57)
  • Cargo.lock is excluded by !**/*.lock
  • crates/cli/tests/snapshots/doctor__doctor_fails_when_active_pf_redirects_are_missing.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/doctor__doctor_fails_when_daemon_socket_is_stale.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/doctor__doctor_fails_when_system_ca_trust_is_missing.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/doctor__doctor_fails_when_system_resolver_is_missing.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/doctor__doctor_fails_with_repair_commands.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/doctor__doctor_on_a_terminal_failing.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/doctor__doctor_on_a_terminal_healthy.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/doctor__doctor_passes_when_required_checks_pass.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/doctor__doctor_tracks_failure_repair_and_identical_recurrence.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/doctor__doctor_warnings_do_not_fail.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/ports__ports_install_fails_on_low_port_conflict_before_writing_prepared_artifacts.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/ports__ports_install_names_low_port_owners.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/ports__ports_install_refuses_a_new_low_port_conflict_when_redirects_already_match.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/setup__setup_manifest_missing_default_plain.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/setup__setup_manifest_missing_default_terminal.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/setup__setup_no_path_configures_system_integrations_and_waits_for_reconciliation.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/setup__setup_non_interactive_fails_before_shell_profile_mutation.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/setup__setup_on_a_terminal.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/setup__setup_pf_apply_conflict_does_not_reinstall_the_helper.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/setup__setup_repairs_from_active_release_helper_metadata.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/setup__setup_stops_at_a_failed_required_step.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/setup__setup_stops_at_a_failed_required_step_plain.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/setup__setup_uses_cached_manifest_with_warning_when_refresh_fails.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/setup__setup_yes_creates_and_uninstall_removes_shell_profile_block.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_accepts_protocol_mismatch_health_after_activation.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_check_json_reports_app_and_managed_resource_updates.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_check_on_a_terminal_renders_status_rows.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_check_reports_app_and_managed_resource_updates.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_check_reports_blocked_managed_resource.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_check_reports_current_managed_resource.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_check_reports_revoked_managed_resource.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_check_reports_unavailable_managed_resource.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_downloads_and_activates_new_app_then_reexecs_managed_resource_continuation.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_normalizes_stale_launch_agent_without_restarting_when_current.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_on_a_terminal_forwards_no_color_to_the_continuation.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_on_a_terminal_renders_a_flow.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_rejects_registered_helper_identity_that_cannot_be_rolled_back.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_reports_current_app_without_restarting_daemon.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_reports_reexec_failure_without_rolling_back_updated_app.snap is excluded by !**/*.snap
  • crates/cli/tests/snapshots/update__update_tests__update_warns_when_pruning_old_app_release_fails.snap is excluded by !**/*.snap
  • crates/platform/src/listener/macos/snapshots/platform__listener__implementation__kernel_table__tests__empty_pcb_fixture_matches_xnu_single_envelope_shape.snap is excluded by !**/*.snap
  • crates/platform/src/listener/macos/snapshots/platform__listener__implementation__kernel_table__tests__live_kernel_table_repeatedly_detects_all_controlled_listener_classes.snap is excluded by !**/*.snap
  • crates/platform/src/listener/macos/snapshots/platform__listener__implementation__kernel_table__tests__malformed_pcb_fixtures_return_deterministic_typed_errors.snap is excluded by !**/*.snap
  • crates/platform/src/listener/macos/snapshots/platform__listener__implementation__kernel_table__tests__pcb_fixture_covers_address_families_states_generations_and_unknown_records.snap is excluded by !**/*.snap
  • crates/platform/src/snapshots/platform__command__tests__bounded_command_accepts_only_the_requested_empty_exit_status.snap is excluded by !**/*.snap
  • crates/platform/src/snapshots/platform__helper__tests__root_port_443.snap is excluded by !**/*.snap
  • crates/platform/src/snapshots/platform__helper__tests__root_port_80.snap is excluded by !**/*.snap
  • crates/platform/src/snapshots/platform__low_port__tests__empty_output.snap is excluded by !**/*.snap
  • crates/platform/src/snapshots/platform__low_port__tests__lsof_owners_are_capped_and_free_ports_have_no_owners.snap is excluded by !**/*.snap
  • crates/platform/src/snapshots/platform__low_port__tests__mixed_ipv4_and_ipv6_wildcard.snap is excluded by !**/*.snap
  • crates/platform/src/snapshots/platform__low_port__tests__named_owner.snap is excluded by !**/*.snap
  • crates/platform/src/snapshots/platform__low_port__tests__nginx_master_workers.snap is excluded by !**/*.snap
  • crates/platform/src/snapshots/platform__low_port__tests__several_pids.snap is excluded by !**/*.snap
  • crates/platform/src/snapshots/platform__low_port__tests__unrelated_or_incomplete_fields.snap is excluded by !**/*.snap
  • crates/platform/tests/snapshots/resolver_config__pf_loopback_tcp_listener_ports_include_ipv4_wildcard_listener.snap is excluded by !**/*.snap
  • crates/platform/tests/snapshots/resolver_config__pf_loopback_tcp_listener_ports_include_ipv6_loopback_and_wildcard_listeners.snap is excluded by !**/*.snap
📒 Files selected for processing (5)
  • .github/workflows/ci.yml
  • DESIGN.md
  • crates/platform/Cargo.toml
  • crates/platform/src/helper.rs
  • crates/platform/src/low_port.rs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.


📝 Walkthrough

Walkthrough

The platform replaces listener-port enumeration with privileged inspection of ports 80 and 443. The helper protocol advances to version 2 and checks for conflicts before applying PF redirects. The CLI reports unavailable ports and available owner details.

Changes

Low-port conflict inspection

Layer / File(s) Summary
Low-port inspection contract and probe
crates/platform/src/low_port.rs, crates/platform/src/command.rs, crates/platform/src/lib.rs, crates/platform/src/listener/*, crates/platform/src/{capability,error,ca,pf}.rs, crates/platform/tests/{resolver_config,unsupported_listener}.rs, DESIGN.md
The platform adds bind-probe availability results and optional process-owner diagnostics from lsof. It removes the former listener-inspection APIs and platform-specific implementations. The command-output function gains an optional exit-code parameter. Design requirements and listener-test coverage are updated.
Privileged helper inspection and PF preflight
crates/platform/src/helper.rs, crates/platform/Cargo.toml, crates/privileged-helper/Cargo.toml, .github/workflows/ci.yml, DESIGN.md, crates/cli/tests/{doctor,setup,update}.rs
The helper protocol and version advance to 2. The helper adds low-port inspection, removes PF reload, and checks ports 80 and 443 before applying redirects. Helper lifecycle operations wait for readiness after bootstrap. CI adds a root-run conflict test, and tests and helper-version fixtures use the updated protocol and versions.
CLI conflict reporting and setup behavior
crates/cli/src/environment.rs, crates/cli/src/commands/{artifact_resource,mod,php,ports}.rs, crates/cli/tests/*.rs, crates/cli/tests/support/resource_cli.rs
The CLI environment delegates inspection to the helper. Port installation reports each unavailable port and its owner details, or an lsof hint when no owner is reported. Tests cover named conflicts, setup failure, and preservation of existing assignments and PF files.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Bug fix · Severity of issue fixed: Low

Sequence Diagram(s)

sequenceDiagram
  participant CLI as ports::install
  participant Environment as ProcessEnvironment
  participant Client as PrivilegedHelperClient
  participant Helper as helper dispatch
  participant Probe as low_port.rs
  CLI->>Environment: inspect_low_ports()
  Environment->>Client: inspect_low_ports()
  Client->>Helper: LowPortInspect
  Helper->>Probe: inspect ports 80 and 443
  Probe-->>Helper: availability and owner data
  Helper-->>Client: LowPorts payload
  Client-->>Environment: LowPortInspection
  Environment-->>CLI: inspection results
  CLI->>CLI: report unavailable ports and owner details
Loading

Merge Risk: ⚪ Minimal · up to b64bd

The change moves the 80/443 conflict check to a root bind probe and makes the helper reject conflicting PF redirects before changing pf. No concrete merge-blocking issue was found in the supplied evidence.

Security Architecture Review

Security architecture risk: 🔵 Low · up to b64bd

The change strengthens port-conflict protection without broadening access to administrator operations. Remaining uncertainty concerns privileged-service upgrades and recovery under interruption or concurrency, which were not fully validated.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • observed — The sensitive outcome remains host-local but privileged: applying system PF redirect configuration through fixed system paths. LowPortInspect itself accepts no arbitrary port, pathname, or command input and inspects only ports 80 and 443.

Trust Boundaries and Controls

  • observed — The helper authenticates Unix peer credentials against the installing UID before reading or dispatching requests. LowPortInspect retains this boundary, and PfApply validates distinct high-port targets before enforcing its new low-port gate. Availability does not depend on executable signing identity or process-owner discovery.

Resilience and Maintainability Implications

  • inferred — The new gate is a point-in-time check, not a reservation against concurrent listener arrival. This limits the guarantee under concurrency, but the base already allowed PF mutation without a root-side availability check; the inspected comparison does not establish a newly introduced or worsened attack path.

Hardening Proposals

  • proposed — Consider failure-injection coverage for interrupted upgrades and rollback of an initially unresponsive helper, including explicit restored-service readiness verification when no previous status was captured. This addresses a pre-existing recovery limitation rather than an observed PR regression.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.78% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 135 functions across 32 files. (3 skipped… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Issue #402 requests a coding fix for the macOS 27 netstat cross-check. The PR removes that cross-check with the obsolete kernel-table listener path and its live test. The PR replaces low-port decisi…
Out of Scope Changes check ✅ Passed The helper protocol changes, low-port diagnostics, CLI integration, PF guard, lifecycle waiting, CI root test, documentation, fixtures, and compatibility test updates support the replacement of kernel…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: root-level checks for ports 80 and 443 and removal of kernel-table inspection.
Full details: Docstring Coverage

Explanation

Docstring coverage is 37.78% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 135 functions across 32 files. (3 skipped: 3 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@clvsh
clvsh added this pull request to stack #410 October 8, 2026 05:13
@codspeed

codspeed Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 7 untouched benchmarks


Comparing feat/root-low-port-inspection (b64bd7a) with feat/loopback-port-probe (4bf0c7c)

Open in CodSpeed

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Single-port conflicts currently lose their owner diagnostics, and the root conflict guard is not exercised by CI. Both should be addressed before merging.

Reviewed changes The full PR was reviewed, including the privileged inspection path, CLI callers, protocol changes, deleted listener API, and updated tests.

  • Root availability checks: LowPortInspect probes ports 80/443 through the helper, and PfApply checks again before changing PF rules.
  • Conflict diagnostics: Bounded lsof execution supplies deduplicated, capped owner details without deciding port availability.
  • CLI integration: ports:install checks before preparing files or accepting current redirects, with setup tests covering apply-time conflict propagation.
  • Protocol and platform cleanup: Helper version 2.0.0/protocol 2 replace the unused reload operation and private kernel-table listener inspection; fixtures and design guidance are updated accordingly.

Validation: all 38 platform library tests passed on Linux. The CLI integration command stopped in the ports suite at the existing platform boundary (low-port frontend is unsupported on linux); macOS/root execution could not be validated on this host. The lsof selector issue was reproduced locally and checked against Apple's source.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

Comment thread crates/platform/src/low_port.rs Outdated
Comment thread crates/platform/src/helper.rs Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No new issues found in this delta. Approval remains withheld while the existing root acceptance-test finding is open.

Reviewed changes Reviewed 6989b9e against the previous review at 604b72c, with the full PR diff checked for context.

  • Replaced separate lsof selectors with one comma-separated selector, preserving owner diagnostics when only one requested port is occupied without weakening command-failure handling.
  • Expanded live macOS regression coverage to inspect one held high port alongside one free port and assert owner details and free-port state.

Validation: cargo test --locked -p platform --lib passed all 38 tests, and cargo fmt --all --check passed. A local Linux lsof reproduction confirmed that split selectors return exit 1 with owner output, while the combined selector returns exit 0 with the same output. The macOS-only regression test and privileged helper behavior could not be executed on this Linux host.

Pullfrog  | Fix it ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

@clvsh
clvsh marked this pull request as ready for review October 8, 2026 05:42
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-08T18:46:30.616370Z b64bd7a New commits
🔒 Security Review ✅ Completed 2026-10-08T05:54:26.434417Z 6989b9e Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6989b9e512

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/platform/src/helper.rs Outdated

#[cfg(target_os = "macos")]
#[test]
#[ignore = "requires root and a free loopback port 80"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Run the root conflict guard in every macOS lane

This is the only test of the root-side PfApply conflict recheck, but #[ignore] excludes it from the workflow's ordinary cargo nextest run (nextest documents that the default runs only non-ignored tests); it also creates the listener in the probing process rather than a separate process. Consequently, no macOS matrix lane verifies the root/cross-process safety boundary even though DESIGN.md:31 now explicitly promises both conditions, so a regression could pass CI and let PF redirect traffic away from an existing service. Add a root CI invocation using a separately spawned listener.

AGENTS.md reference: AGENTS.md:L3-L4

Useful? React with 👍 / 👎.

@clvsh clvsh Oct 8, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in b64bd7a. Every macOS CI lane now builds as its regular user, verifies the exact ignored platform test in nextest's JSON listing, and runs only that executable/test with sudo. The test holds ports 80 and 443 in a separate native process and checks LowPortInspect, actual PfApply rejection, unchanged PF state, and cleanup. #403 inherits this gate for macOS 27. The root acceptance step passed on macOS 14, 15, 26, and 27 in the combined CI run. The combined CI run also passed the full normal suite in all four macOS lanes, plus Linux and Windows.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No new issues found in this delta. Approval remains withheld while the existing root acceptance-test finding is open.

Reviewed changes Reviewed 4771790 against the prior review at 6989b9e, with the full PR diff checked for context.

  • Added bootstrap readiness waiting to helper installation and rollback restoration, retrying missing or refused socket connections without retrying authentication or invalid-response failures.
  • Added macOS socket regression tests for delayed socket creation, a socket that never appears, and invalid lifecycle responses.
  • Updated lifecycle design guidance to document socket-availability waiting after registration and restoration.

Validation: cargo fmt --all --check passed, and the final cargo test --locked -p platform --lib run passed all 38 tests on Linux. An intermediate rerun failed the unchanged random-filename test at pf.rs:1661 (assertion failed: !first.file_name().is_some_and(|name| name.contains(&process_id))); it passed on rerun. The new macOS-only socket tests and privileged helper behavior could not be executed on this host.

Pullfrog  | Fix it ➔ | View workflow run | Using gpt-6.1-sol | 𝕏

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4771790f29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

&& let Some(pid) = pid
&& let Some(command) = command
&& let Some((address, port)) = value.rsplit_once(':')
&& matches!(address, "*" | "127.0.0.1" | "[::]")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Report owners bound to specific IPv4 interfaces

When a service listens on a specific non-loopback IPv4 address such as 192.168.1.10:80, the required 0.0.0.0:80 probe can mark the port unavailable and lsof returns that address, but this whitelist discards the otherwise valid PID and command. The CLI consequently claims that it could not identify the process and makes the user run the same lsof command manually, contrary to the owner-reporting behavior specified in DESIGN.md. The upstream lsof field-output documentation confirms that the n field contains the Internet address, so relevant interface-specific IPv4 records need to be associated with the failed wildcard probe rather than dropped.

AGENTS.md reference: AGENTS.md:L4-L4

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not reproduce the proposed bind conflict. On this macOS 27 host, a separate LAN-only IPv4 holder left both 127.0.0.1 and 0.0.0.0 probes free, with SO_REUSEADDR both on and off; the public platform probe returned available. Inspection therefore returns before lsof. These additional measurements used an unprivileged caller, so they do not prove every root/OS combination. I am keeping the address filter: widening it can list an unrelated LAN service during a real loopback conflict. A root or other supported-OS counterexample would justify revisiting that decision. I did fix the related diagnostic ambiguity in b64bd7a: messages now list reported listeners without claiming which one caused the IPv4 bind failure. A mixed IPv4/IPv6-wildcard fixture covers that wording.

@clvsh

clvsh commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Reviewed CodeRabbit’s documentation-coverage warning and the root acceptance concern. No bulk docstring change is planned for the percentage target. The root test now observes a separate process on each low port and is an explicit gate in every macOS CI lane, including macOS 27 through #403. The behavioral findings and the LAN-owner hypothesis are answered in their threads.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes Reviewed b64bd7a since the prior review at 4771790, with the full PR diff checked for context; the three rebased predecessor commits have identical patches to their previously reviewed versions.

  • Added Root CI coverage that builds as the regular CI user, verifies selection of the exact ignored test, and runs only its executable under sudo in every declared macOS lane.
  • Expanded Cross-process acceptance coverage to test ports 80 and 443 separately, verify the holder PID through LowPortInspect, exercise actual PfApply rejection, check unchanged active PF state, and confirm port availability after child cleanup.
  • Revised Listener diagnostics and design guidance to distinguish unavailable IPv4 ports from reported listeners, avoiding attribution that lsof wildcard notation cannot establish.
  • Updated Diagnostic snapshots to cover conflict messages, unidentified listeners, and mixed IPv4/IPv6 wildcard output.

Validation: all 38 portable platform library tests passed on Linux, and cargo fmt --all --check passed. The new macOS/root acceptance test cannot run on this host; its CI lanes remain queued, so execution of the new gate is still pending.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

@clvsh
clvsh merged commit 5b0ee6e into main Oct 8, 2026
14 of 20 checks passed
@clvsh
clvsh deleted the feat/root-low-port-inspection branch October 8, 2026 23:36
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.

test: netstat prints nothing when run from a Rust test binary on macOS 27, failing the listener snapshot test

1 participant