[GH-ISSUE #7594] [Bug] Failed Frida process discovery omits the selected endpoint or device ID #4527

Closed
opened 2026-10-31 00:50:30 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 27, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7594

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Provider or capability discovery

Observed behavior

Failed list-frida-processes calls return JSON errors with no record of the endpoint or device ID passed by the caller. Two different remote selections produce identical errors, and the missing-device recovery refers to an unnamed selected device.

Observed commands included:

node scripts/rea.mjs list-frida-processes --remote-address 127.0.0.1:61245 --format json
node scripts/rea.mjs list-frida-processes --remote-address 127.0.0.1:61276 --format json
node scripts/rea.mjs list-frida-processes --device-id verify-c145-missing-device --format json

The remote endpoints were allocated and closed by the fixture before invocation. Each remote call exited 1 with capability_unavailable, reason Unable to connect to remote frida-server, and advice to choose another analysis or target. Neither selected address appears in any output field. The device call exited 1 with provider_timeout and the documented fixed 1000 ms lookup deadline, but no selected ID. Stderr was empty. The explicit local-device control succeeded and returned device_id: local.

Reproduction

  1. Use the baseline below with its built runtime and locked optional Frida binding available. Put Node.js 24.22.1 on PATH and run from the checkout root.
  2. Execute this fixture. It creates isolated HOME/XDG state, allocates and closes its own loopback endpoints, and removes its temporary directories afterward. No target is attached or instrumented.
python3 -I - <<'PYTHON'
import json, os, socket, subprocess, tempfile
from pathlib import Path

with tempfile.TemporaryDirectory() as state:
    env = {"PATH": os.environ["PATH"]}
    for key in ("HOME", "XDG_CONFIG_HOME", "XDG_CACHE_HOME",
                "XDG_DATA_HOME", "XDG_STATE_HOME", "TMPDIR"):
        directory = Path(state, key)
        directory.mkdir()
        env[key] = str(directory)

    for trial in range(2):
        with socket.socket() as listener:
            listener.bind(("127.0.0.1", 0))
            endpoint = f"127.0.0.1:{listener.getsockname()[1]}"
        # The listener is closed before REA runs.
        for option, selected in (("--remote-address", endpoint),
                                 ("--device-id", "verify-c145-missing-device")):
            command = ["node", "scripts/rea.mjs", "list-frida-processes",
                       option, selected, "--format", "json"]
            run = subprocess.run(command, env=env, text=True,
                                 capture_output=True, timeout=30)
            error = json.loads(run.stdout)
            print(json.dumps({"trial": trial + 1, "selected": selected,
                              "exit": run.returncode,
                              "selector_in_output": selected in
                                  (run.stdout + run.stderr),
                              "error": error}))

    control = subprocess.run(
        ["node", "scripts/rea.mjs", "list-frida-processes",
         "--device-id", "local", "--format", "json"],
        env=env, text=True, capture_output=True, timeout=30)
    print(json.dumps({"control_exit": control.returncode,
                      "device_id": json.loads(control.stdout)["device_id"]}))
PYTHON
  1. Each of the four failing calls prints exit: 1 and selector_in_output: false. The control prints control_exit: 0 and device_id: local. This exact fixture reproduced both failure forms twice. Earlier independent trials also reproduced each twice with a fixed loopback port and twice with freshly allocated ports.

Expected behavior

A complete failure result should retain the caller's non-authentication selection, such as the remote address or explicit device ID, in a message or structured details. A connection refusal should identify the endpoint that failed and give connection-specific recovery guidance.

The repository's caller-input preservation invariant applies to the accepted selectors. Authentication values must remain excluded. This report does not require creating Evidence for failed discovery, changing the existing error codes, or changing the documented lookup deadline.

Impact and scope

P2: standalone failure results lose the selection needed to correlate and diagnose failed discovery calls. Two distinct failed remote selections returned byte-identical errors. The device error asks the caller to check a device without identifying it, and the remote error's public advice concerns a target/analysis rather than the connection.

The practical workaround is to retain the original invocation beside its error and read the selector there. Discovery still fails safely. No data loss, target mutation, or security-boundary crossing was observed. Verified scope is the built CLI on macOS with real Frida bindings; MCP projection, physical devices, and successful remote-server connections were not exercised.

REA version

Exact stdout from node scripts/rea.mjs --version:

6.8.0

Source baseline: 65f1c447344a423fa2785847dbcea1e9a9e2454a.

Runtime and platform

Node.js v24.22.1; macOS 27.0.1; darwin arm64; installed Frida Node binding 17.23.2. No Frida server or target instrumentation was required.

Target and artifact context

Target-free process discovery. Remote inputs were closed loopback endpoints; the explicit missing-device input was a synthetic identifier. The local control enumerated processes without attaching to them.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

The two freshly allocated endpoint calls above returned this same complete JSON document:

{"code":"capability_unavailable","category":"unsupported_provider","message":"This analysis is unavailable for the current target. Choose another analysis or target.","retryable":false,"remediation":{"action":"This analysis is unavailable for the current target. Choose another analysis or target."},"details":{"provider_id":"frida","operation":"list_frida_processes","reason":"Unable to connect to remote frida-server"}}

The explicit missing-device call returned:

{"code":"provider_timeout","category":"timeout","message":"Frida device lookup reached its 1000 ms deadline (deadlineExpired). This release has no runtime override.","retryable":true,"remediation":{"action":"The 1000 ms Frida device lookup has no runtime override. Confirm the selected device is attached, then retry. Another REA timeout does not raise this lookup."},"recovery":{"kind":"inspect_timeout_state","operation":"list_frida_processes","timeout_ms":1000},"details":{"operation":"list_frida_processes","timeout_ms":1000}}

Contract and reachability at the baseline:

  • AGENTS.md:13 requires preservation of caller-selected inputs and distinguishes them from transport authentication credentials. Its Architecture and Cleanup section requires meaningful failure reasons to survive boundaries.
  • docs/frida-instrumentation.md:5,29 describes remote host/port selection, authentication exclusion, and the fixed local lookup deadline. The non-authentication device/endpoint preservation sentence specifically describes Evidence; this report relies on the broader input-preservation invariant for failure output.
  • src/contracts/fridaToolContracts.ts:80-98 describes selected-device/remote process discovery. src/cli/fridaCommands.ts:104-142 accepts and forwards the exercised selectors.

Failure path at the baseline:

  • src/frida/FridaInstrumentationManager.ts:235-300 still has the complete selector when discovery fails. Its error helper receives the remote object but no device ID.
  • src/frida/FridaInstrumentationManager.ts:1240-1265 creates the local lookup timeout without the selected ID. src/application/frida/FridaInstrumentationManager.test.ts:223-264 confirms that the deadline classification is intentional and distinguishes other device-manager failures.
  • src/frida/FridaInstrumentationManager.ts:1270-1310,1595-1644 rethrows remote acquisition failure and builds the provider error without retaining the address in public diagnostics. The remote object supplies authentication redaction.
  • src/domain/analysisErrorPresentation.ts:426-430 supplies the generic analysis/target message when no contextual message exists.

Typed outcome or recovery expected

Retain the selected endpoint or explicit device ID in the typed failure, while excluding authentication credentials. For the remote case, explain that connection to that endpoint failed and direct recovery toward its server/address. Keep genuine connection and lookup failures distinct from invalid selector input.

Analysis or suspected cause

Source-derived explanation: the device lookup timeout is created without its selection, while the remote error conversion uses its remote argument for redaction and omits the address from the returned diagnostic. Public projection consequently has no selector to preserve.

Additional context

Read-only searches covered open and closed issues, issue comments, and open/closed/merged PRs. No matching report was found. Relevant adjacent reports have different restoration criteria:

  • #6028 and closed PR #6387 concern resume refusal for an already-running session, repaired with a session-state input error.
  • #2527 concerns conflicting options on an already-retained endpoint, repaired by preserving an input error.
  • #5092 concerns advertising the required selector before invocation, not retaining an admitted selector after native failure.
  • #5451 concerns JEB discovery recovery at a separate provider boundary.
  • #5910 and merged PR #6014 concern effective deadline/limit values and controls. The observed local error already names its fixed budget and lack of override; no regression of that closure is asserted.

Prepared from independent real-CLI verification with AI assistance. The report makes no claim about the separate instrumentation/attach path.

Originally created by @coygeek on GitHub (Oct 27, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7594 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Provider or capability discovery ### Observed behavior Failed `list-frida-processes` calls return JSON errors with no record of the endpoint or device ID passed by the caller. Two different remote selections produce identical errors, and the missing-device recovery refers to an unnamed selected device. Observed commands included: ```sh node scripts/rea.mjs list-frida-processes --remote-address 127.0.0.1:61245 --format json node scripts/rea.mjs list-frida-processes --remote-address 127.0.0.1:61276 --format json node scripts/rea.mjs list-frida-processes --device-id verify-c145-missing-device --format json ``` The remote endpoints were allocated and closed by the fixture before invocation. Each remote call exited 1 with `capability_unavailable`, reason `Unable to connect to remote frida-server`, and advice to choose another analysis or target. Neither selected address appears in any output field. The device call exited 1 with `provider_timeout` and the documented fixed 1000 ms lookup deadline, but no selected ID. Stderr was empty. The explicit local-device control succeeded and returned `device_id: local`. ### Reproduction 1. Use the baseline below with its built runtime and locked optional Frida binding available. Put Node.js 24.22.1 on PATH and run from the checkout root. 2. Execute this fixture. It creates isolated HOME/XDG state, allocates and closes its own loopback endpoints, and removes its temporary directories afterward. No target is attached or instrumented. ```sh python3 -I - <<'PYTHON' import json, os, socket, subprocess, tempfile from pathlib import Path with tempfile.TemporaryDirectory() as state: env = {"PATH": os.environ["PATH"]} for key in ("HOME", "XDG_CONFIG_HOME", "XDG_CACHE_HOME", "XDG_DATA_HOME", "XDG_STATE_HOME", "TMPDIR"): directory = Path(state, key) directory.mkdir() env[key] = str(directory) for trial in range(2): with socket.socket() as listener: listener.bind(("127.0.0.1", 0)) endpoint = f"127.0.0.1:{listener.getsockname()[1]}" # The listener is closed before REA runs. for option, selected in (("--remote-address", endpoint), ("--device-id", "verify-c145-missing-device")): command = ["node", "scripts/rea.mjs", "list-frida-processes", option, selected, "--format", "json"] run = subprocess.run(command, env=env, text=True, capture_output=True, timeout=30) error = json.loads(run.stdout) print(json.dumps({"trial": trial + 1, "selected": selected, "exit": run.returncode, "selector_in_output": selected in (run.stdout + run.stderr), "error": error})) control = subprocess.run( ["node", "scripts/rea.mjs", "list-frida-processes", "--device-id", "local", "--format", "json"], env=env, text=True, capture_output=True, timeout=30) print(json.dumps({"control_exit": control.returncode, "device_id": json.loads(control.stdout)["device_id"]})) PYTHON ``` 3. Each of the four failing calls prints `exit: 1` and `selector_in_output: false`. The control prints `control_exit: 0` and `device_id: local`. This exact fixture reproduced both failure forms twice. Earlier independent trials also reproduced each twice with a fixed loopback port and twice with freshly allocated ports. ### Expected behavior A complete failure result should retain the caller's non-authentication selection, such as the remote address or explicit device ID, in a message or structured details. A connection refusal should identify the endpoint that failed and give connection-specific recovery guidance. The repository's caller-input preservation invariant applies to the accepted selectors. Authentication values must remain excluded. This report does not require creating Evidence for failed discovery, changing the existing error codes, or changing the documented lookup deadline. ### Impact and scope P2: standalone failure results lose the selection needed to correlate and diagnose failed discovery calls. Two distinct failed remote selections returned byte-identical errors. The device error asks the caller to check a device without identifying it, and the remote error's public advice concerns a target/analysis rather than the connection. The practical workaround is to retain the original invocation beside its error and read the selector there. Discovery still fails safely. No data loss, target mutation, or security-boundary crossing was observed. Verified scope is the built CLI on macOS with real Frida bindings; MCP projection, physical devices, and successful remote-server connections were not exercised. ### REA version Exact stdout from `node scripts/rea.mjs --version`: ```text 6.8.0 ``` Source baseline: `65f1c447344a423fa2785847dbcea1e9a9e2454a`. ### Runtime and platform Node.js v24.22.1; macOS 27.0.1; darwin arm64; installed Frida Node binding 17.23.2. No Frida server or target instrumentation was required. ### Target and artifact context Target-free process discovery. Remote inputs were closed loopback endpoints; the explicit missing-device input was a synthetic identifier. The local control enumerated processes without attaching to them. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence The two freshly allocated endpoint calls above returned this same complete JSON document: ```json {"code":"capability_unavailable","category":"unsupported_provider","message":"This analysis is unavailable for the current target. Choose another analysis or target.","retryable":false,"remediation":{"action":"This analysis is unavailable for the current target. Choose another analysis or target."},"details":{"provider_id":"frida","operation":"list_frida_processes","reason":"Unable to connect to remote frida-server"}} ``` The explicit missing-device call returned: ```json {"code":"provider_timeout","category":"timeout","message":"Frida device lookup reached its 1000 ms deadline (deadlineExpired). This release has no runtime override.","retryable":true,"remediation":{"action":"The 1000 ms Frida device lookup has no runtime override. Confirm the selected device is attached, then retry. Another REA timeout does not raise this lookup."},"recovery":{"kind":"inspect_timeout_state","operation":"list_frida_processes","timeout_ms":1000},"details":{"operation":"list_frida_processes","timeout_ms":1000}} ``` Contract and reachability at the baseline: - `AGENTS.md:13` requires preservation of caller-selected inputs and distinguishes them from transport authentication credentials. Its Architecture and Cleanup section requires meaningful failure reasons to survive boundaries. - `docs/frida-instrumentation.md:5,29` describes remote host/port selection, authentication exclusion, and the fixed local lookup deadline. The non-authentication device/endpoint preservation sentence specifically describes Evidence; this report relies on the broader input-preservation invariant for failure output. - `src/contracts/fridaToolContracts.ts:80-98` describes selected-device/remote process discovery. `src/cli/fridaCommands.ts:104-142` accepts and forwards the exercised selectors. Failure path at the baseline: - `src/frida/FridaInstrumentationManager.ts:235-300` still has the complete selector when discovery fails. Its error helper receives the remote object but no device ID. - `src/frida/FridaInstrumentationManager.ts:1240-1265` creates the local lookup timeout without the selected ID. `src/application/frida/FridaInstrumentationManager.test.ts:223-264` confirms that the deadline classification is intentional and distinguishes other device-manager failures. - `src/frida/FridaInstrumentationManager.ts:1270-1310,1595-1644` rethrows remote acquisition failure and builds the provider error without retaining the address in public diagnostics. The remote object supplies authentication redaction. - `src/domain/analysisErrorPresentation.ts:426-430` supplies the generic analysis/target message when no contextual message exists. ### Typed outcome or recovery expected Retain the selected endpoint or explicit device ID in the typed failure, while excluding authentication credentials. For the remote case, explain that connection to that endpoint failed and direct recovery toward its server/address. Keep genuine connection and lookup failures distinct from invalid selector input. ### Analysis or suspected cause Source-derived explanation: the device lookup timeout is created without its selection, while the remote error conversion uses its remote argument for redaction and omits the address from the returned diagnostic. Public projection consequently has no selector to preserve. ### Additional context Read-only searches covered open and closed issues, issue comments, and open/closed/merged PRs. No matching report was found. Relevant adjacent reports have different restoration criteria: - #6028 and closed PR #6387 concern resume refusal for an already-running session, repaired with a session-state input error. - #2527 concerns conflicting options on an already-retained endpoint, repaired by preserving an input error. - #5092 concerns advertising the required selector before invocation, not retaining an admitted selector after native failure. - #5451 concerns JEB discovery recovery at a separate provider boundary. - #5910 and merged PR #6014 concern effective deadline/limit values and controls. The observed local error already names its fixed budget and lack of override; no regression of that closure is asserted. Prepared from independent real-CLI verification with AI assistance. The report makes no claim about the separate instrumentation/attach path.
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#4527
No description provided.