[PR #2507] [MERGED] fix(pcap): name the host tool to configure in capability refusals #5284

Closed
opened 2026-10-31 01:05:26 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2507
Author: @kaoru0822-kitauji
Created: 10/13/2026
Status: ✅ Merged
Merged: 10/13/2026
Merged by: @morluto

Base: main ← Head: fix/pcap-capability-remediation


📝 Commits (2)

  • 47cd07b fix(pcap): name the host tool to configure in capability refusals
  • b72d828 test(pcap): cover the Linux prlimit refusal guidance

📊 Changes

8 files changed (+102 additions, -34 deletions)

View changed files

📝 src/pcap/PcapCommand.ts (+3 -5)
📝 src/pcap/PcapConfiguration.ts (+19 -0)
📝 src/pcap/PcapNativeBound.ts (+17 -7)
📝 src/pcap/PcapProvider.ts (+4 -6)
📝 src/pcap/PcapSnapshot.ts (+1 -1)
📝 tests/boundary/cli/pcapCli.test.ts (+23 -9)
📝 tests/boundary/pcap/pcapProvider.test.ts (+27 -2)
📝 tests/boundary/pcap/pcapProviderCrossPlatform.test.ts (+8 -4)

📄 Description

Summary

Every host-tool refusal in the new inspect_pcap_capture / inspect_pcap_client family (9581e067a) told the caller "This analysis is unavailable for the current target. Choose another analysis or target." That includes inspect_pcap_client, which has no target at all. The real cause, such as tshark missing from PATH, a relative REA_TSHARK_COMMAND, the unsupported macOS capture boundary or an unusable Linux prlimit, was available only in details.reason. So an agent following remediation.action would try another target instead of fixing the installation. The sibling inspect_packet_capture adapter (TsharkCaptureProvider) and sigrok/WABT already give these refusals a userMessage. The pcap family never did.

No linked issue: found by a CLI sweep of new commands on a host without Wireshark.

Problem and expected behavior

Smallest trigger, on any host without Wireshark: rea inspect-pcap-client --format json

Before:

{"code":"capability_unavailable","message":"This analysis is unavailable for the current target. Choose another analysis or target.", "remediation":{"action":"This analysis is unavailable for the current target. Choose another analysis or target."}, "details":{"reason":"Cannot run selected tool tshark: spawn tshark ENOENT"}}

After:

{"code":"capability_unavailable","message":"Cannot run selected tool tshark: spawn tshark ENOENT. Supply Wireshark 4.x tshark and capinfos on PATH or through absolute REA_TSHARK_COMMAND and REA_CAPINFOS_COMMAND; REA does not install them.", "remediation":{"action":"<same>"}, ...}

Violated invariant: a host or tool refusal names what to configure. It does not send the caller to another target (the #1224 precedent for pwntools/EVMole/firmware/LLDB, and expectConfigurationRefusal in the CLI harness).

Change and scope

  • src/pcap/PcapConfiguration.ts already owns the tool environment names. It now also owns pcapToolUnavailable, the one constructor for tool refusals. All three tool-refusal sites use it: spawn ENOENT/EACCES/Windows batch and the version probe failure in PcapCommand, and PcapConfigurationFailure in PcapProvider. The reason is unchanged; only userMessage is added. Missing terminal punctuation is completed so the two sentences don't run together.
  • PcapNativeBound: the macOS/unsupported-host refusal uses its own reason as userMessage, because it already states the Linux/Windows requirement. The Linux limiter refusal now includes the underlying cause (e.g. REA_TSHARK_PRLIMIT_COMMAND must be absolute. or ENOENT … realpath '/usr/bin/prlimit') and names REA_TSHARK_PRLIMIT_COMMAND. Before, it gave only a generic sentence.
  • PcapSnapshot: a PrivateRuntimeRootUnavailableError now keeps its retryable flag, as the WABT and source-map adapters already do. Before, a transient workspace refusal was projected as permanent.

Not included: the two TShark adapters (src/captures/TsharkCaptureProvider.ts and src/pcap/) duplicate tool selection and refusal wording. Merging them is a larger ownership decision. The generic projection for non-retryable PrivateRuntimeRootUnavailableError is shared by every runtime-root consumer, so it is left unchanged here.

Contribution scope: not applicable (an ordinary fix within existing boundaries).

Contract and boundary impact

  • Semantic owner and earliest changed stage: the pcap provider's capability refusal construction (src/pcap).

  • Contribution scope fit and linked maintainer decision: not applicable.

  • CLI and MCP/tool-catalog contract: no schema change. Error message/remediation.action text changes for capability_unavailable refusals of inspect_pcap_capture/inspect_pcap_client. Codes, categories and details are unchanged.

  • Provider, bridge, target-format, or platform compatibility: none.

  • Evidence, artifact, provenance, or reconstruction contract: none.

  • Target selection, authority, upstream behavior, and cleanup details: unchanged. Refusals still happen before any capture byte is read.

  • Generated metadata, package, or installation impact: none.

  • Documentation or usability only; no target interaction.

Evidence and regression coverage

  • Tests added or updated:
    • tests/boundary/cli/pcapCli.test.ts: public CLI for both commands with missing tools, plus a relative REA_TSHARK_COMMAND, through the shared expectConfigurationRefusal helper.
    • tests/boundary/pcap/pcapProviderCrossPlatform.test.ts: the unsupported-host refusal states the Linux/Windows requirement (runs on macOS).
    • tests/boundary/pcap/pcapProvider.test.ts (Linux): tool configuration refusals carry the guidance, and a new case covers a relative REA_TSHARK_PRLIMIT_COMMAND.
  • Base reproduction: with the src/pcap changes stashed, the 3 new CLI cases fail (generic message); with them, all 5 pass.
  • User-visible output: see above. Real MCP stdio inspect_pcap_client/inspect_pcap_capture return the same text in error.message.
  • Remaining proof gaps: the Linux-only pcapProvider.test.ts cases (including the prlimit case) did not run locally on macOS; they run in CI. I checked the prlimit message text against dist by importing preparePcapNativeBound with process.platform overridden to linux. Real Wireshark is not installed here, so no real-TShark run.

Validation performed

  • npm run test:focused -- tests/boundary/cli/pcapCli.test.ts — 5 passed (3 failed with the fix stashed)
  • npm run test:focused -- tests/boundary/pcap/*.test.ts tests/boundary/mcp/pcapMcp.test.ts tests/boundary/cli/pcapCli.test.ts — 11 passed, 19 skipped (Linux-only). One failure, pcapProviderCrossPlatform "rejects a path that is not a readable file", fails identically on unmodified main on macOS: the host-boundary refusal precedes the path check there.
  • npm run test:local -- src/pcap/PcapConfiguration.test.ts src/pcap/PcapOutput.test.ts src/domain/analysisErrorProjection.test.ts src/domain/explicitSensitiveFailure.test.ts — 92 passed
  • npm run check:fast, npm run typecheck, npm run format:check — pass
  • Real CLI (scripts/rea.mjs) and real MCP stdio client on macOS without Wireshark: missing tools, a version-less tool (/bin/echo), and version-reporting stubs that reach the macOS boundary refusal. All now print the specific guidance.

Cost: each refusal gains about 100 characters, repeated in message and remediation.action (~200 bytes on a one-off error). In exchange, the agent no longer tries another target after a host refusal.

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: macOS real CLI/MCP. Linux paths are covered by CI's boundary tests.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: messages repeat caller-selected tool paths that already appear in details.reason, and explicit-value redaction still applies to userMessage.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • PCAP setup failures now provide clearer guidance for missing or unusable Wireshark tools, including requirements for absolute executable paths.
    • Unsupported memory-limiting options now explain which platform capabilities are required and how to address setup failures.
    • Retryability details are preserved when private runtime setup is unavailable.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/2507 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/13/2026 **Status:** ✅ Merged **Merged:** 10/13/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `fix/pcap-capability-remediation` --- ### 📝 Commits (2) - [`47cd07b`](https://github.com/morluto/rea/commit/47cd07bf1e03d54204d2fc2d77d8478039adf3f7) fix(pcap): name the host tool to configure in capability refusals - [`b72d828`](https://github.com/morluto/rea/commit/b72d8286288d2fe14c77bddbd1c5d7aa9c950204) test(pcap): cover the Linux prlimit refusal guidance ### 📊 Changes **8 files changed** (+102 additions, -34 deletions) <details> <summary>View changed files</summary> 📝 `src/pcap/PcapCommand.ts` (+3 -5) 📝 `src/pcap/PcapConfiguration.ts` (+19 -0) 📝 `src/pcap/PcapNativeBound.ts` (+17 -7) 📝 `src/pcap/PcapProvider.ts` (+4 -6) 📝 `src/pcap/PcapSnapshot.ts` (+1 -1) 📝 `tests/boundary/cli/pcapCli.test.ts` (+23 -9) 📝 `tests/boundary/pcap/pcapProvider.test.ts` (+27 -2) 📝 `tests/boundary/pcap/pcapProviderCrossPlatform.test.ts` (+8 -4) </details> ### 📄 Description ## Summary Every host-tool refusal in the new `inspect_pcap_capture` / `inspect_pcap_client` family (9581e067a) told the caller **"This analysis is unavailable for the current target. Choose another analysis or target."** That includes `inspect_pcap_client`, which has no target at all. The real cause, such as `tshark` missing from PATH, a relative `REA_TSHARK_COMMAND`, the unsupported macOS capture boundary or an unusable Linux `prlimit`, was available only in `details.reason`. So an agent following `remediation.action` would try another target instead of fixing the installation. The sibling `inspect_packet_capture` adapter (`TsharkCaptureProvider`) and sigrok/WABT already give these refusals a `userMessage`. The pcap family never did. No linked issue: found by a CLI sweep of new commands on a host without Wireshark. ## Problem and expected behavior Smallest trigger, on any host without Wireshark: `rea inspect-pcap-client --format json` Before: ```json {"code":"capability_unavailable","message":"This analysis is unavailable for the current target. Choose another analysis or target.", "remediation":{"action":"This analysis is unavailable for the current target. Choose another analysis or target."}, "details":{"reason":"Cannot run selected tool tshark: spawn tshark ENOENT"}} ``` After: ```json {"code":"capability_unavailable","message":"Cannot run selected tool tshark: spawn tshark ENOENT. Supply Wireshark 4.x tshark and capinfos on PATH or through absolute REA_TSHARK_COMMAND and REA_CAPINFOS_COMMAND; REA does not install them.", "remediation":{"action":"<same>"}, ...} ``` Violated invariant: a host or tool refusal names what to configure. It does not send the caller to another target (the #1224 precedent for pwntools/EVMole/firmware/LLDB, and `expectConfigurationRefusal` in the CLI harness). ## Change and scope - `src/pcap/PcapConfiguration.ts` already owns the tool environment names. It now also owns `pcapToolUnavailable`, the one constructor for tool refusals. All three tool-refusal sites use it: spawn ENOENT/EACCES/Windows batch and the version probe failure in `PcapCommand`, and `PcapConfigurationFailure` in `PcapProvider`. The reason is unchanged; only `userMessage` is added. Missing terminal punctuation is completed so the two sentences don't run together. - `PcapNativeBound`: the macOS/unsupported-host refusal uses its own reason as `userMessage`, because it already states the Linux/Windows requirement. The Linux limiter refusal now includes the underlying cause (e.g. `REA_TSHARK_PRLIMIT_COMMAND must be absolute.` or `ENOENT … realpath '/usr/bin/prlimit'`) and names `REA_TSHARK_PRLIMIT_COMMAND`. Before, it gave only a generic sentence. - `PcapSnapshot`: a `PrivateRuntimeRootUnavailableError` now keeps its `retryable` flag, as the WABT and source-map adapters already do. Before, a transient workspace refusal was projected as permanent. Not included: the two TShark adapters (`src/captures/TsharkCaptureProvider.ts` and `src/pcap/`) duplicate tool selection and refusal wording. Merging them is a larger ownership decision. The generic projection for non-retryable `PrivateRuntimeRootUnavailableError` is shared by every runtime-root consumer, so it is left unchanged here. Contribution scope: not applicable (an ordinary fix within existing boundaries). ## Contract and boundary impact - Semantic owner and earliest changed stage: the pcap provider's capability refusal construction (`src/pcap`). - Contribution scope fit and linked maintainer decision: not applicable. - CLI and MCP/tool-catalog contract: no schema change. Error `message`/`remediation.action` text changes for `capability_unavailable` refusals of `inspect_pcap_capture`/`inspect_pcap_client`. Codes, categories and `details` are unchanged. - Provider, bridge, target-format, or platform compatibility: none. - Evidence, artifact, provenance, or reconstruction contract: none. - Target selection, authority, upstream behavior, and cleanup details: unchanged. Refusals still happen before any capture byte is read. - Generated metadata, package, or installation impact: none. - [x] Documentation or usability only; no target interaction. ## Evidence and regression coverage - Tests added or updated: - `tests/boundary/cli/pcapCli.test.ts`: public CLI for both commands with missing tools, plus a relative `REA_TSHARK_COMMAND`, through the shared `expectConfigurationRefusal` helper. - `tests/boundary/pcap/pcapProviderCrossPlatform.test.ts`: the unsupported-host refusal states the Linux/Windows requirement (runs on macOS). - `tests/boundary/pcap/pcapProvider.test.ts` (Linux): tool configuration refusals carry the guidance, and a new case covers a relative `REA_TSHARK_PRLIMIT_COMMAND`. - Base reproduction: with the `src/pcap` changes stashed, the 3 new CLI cases fail (generic message); with them, all 5 pass. - User-visible output: see above. Real MCP stdio `inspect_pcap_client`/`inspect_pcap_capture` return the same text in `error.message`. - Remaining proof gaps: the Linux-only `pcapProvider.test.ts` cases (including the prlimit case) did not run locally on macOS; they run in CI. I checked the prlimit message text against `dist` by importing `preparePcapNativeBound` with `process.platform` overridden to `linux`. Real Wireshark is not installed here, so no real-TShark run. ## Validation performed - `npm run test:focused -- tests/boundary/cli/pcapCli.test.ts` — 5 passed (3 failed with the fix stashed) - `npm run test:focused -- tests/boundary/pcap/*.test.ts tests/boundary/mcp/pcapMcp.test.ts tests/boundary/cli/pcapCli.test.ts` — 11 passed, 19 skipped (Linux-only). One failure, `pcapProviderCrossPlatform` "rejects a path that is not a readable file", fails identically on unmodified main on macOS: the host-boundary refusal precedes the path check there. - `npm run test:local -- src/pcap/PcapConfiguration.test.ts src/pcap/PcapOutput.test.ts src/domain/analysisErrorProjection.test.ts src/domain/explicitSensitiveFailure.test.ts` — 92 passed - `npm run check:fast`, `npm run typecheck`, `npm run format:check` — pass - Real CLI (`scripts/rea.mjs`) and real MCP stdio client on macOS without Wireshark: missing tools, a version-less tool (`/bin/echo`), and version-reporting stubs that reach the macOS boundary refusal. All now print the specific guidance. Cost: each refusal gains about 100 characters, repeated in `message` and `remediation.action` (~200 bytes on a one-off error). In exchange, the agent no longer tries another target after a host refusal. ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: macOS real CLI/MCP. Linux paths are covered by CI's boundary tests. - Package or release metadata impact: none. - Security, privacy, process, or containment review: messages repeat caller-selected tool paths that already appear in `details.reason`, and explicit-value redaction still applies to `userMessage`. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * PCAP setup failures now provide clearer guidance for missing or unusable Wireshark tools, including requirements for absolute executable paths. * Unsupported memory-limiting options now explain which platform capabilities are required and how to address setup failures. * Retryability details are preserved when private runtime setup is unavailable. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:05:26 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#5284
No description provided.