[GH-ISSUE #6839] [Bug] Signal recording named "-" is routed to stdin instead of its private copy #4180

Closed
opened 2026-10-31 00:47:29 +00:00 by bsakaguchi · 0 comments
Owner

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

Before submitting

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

Area

Evidence, artifacts, or reconstruction

Observed behavior

On unreleased main, SignalRecordingService.decode accepts an existing recording whose basename is -, copies it into its private workspace, and launches the producer with --input-file=-. Sigrok-cli 0.7.2 treats that operand as stdin. REA launches it with ignored stdin, so it receives an empty stream instead of the selected recording.

Argument generation and input bytes were observed through the production service/provider with an inert command-boundary simulator. Real sigrok decoding and the CLI/MCP transports were not executed. Sigrok's interpretation is established from its tagged source.

Reproduction

The executed boundary probe created identical 388-byte UART VCD recordings named control.vcd and -, then called the production SignalRecordingService backed by SigrokRecordingProvider for each absolute path:

await service.decode({
  path,
  decoders: "uart:rx=RX:baudrate=9600",
  input_format: "vcd",
  annotations: "uart=rx-data"
});

The probe used the production file reader, private runtime, process launcher, service validation and cleanup. Its injected launcher ran a Node script in place of sigrok/prlimit; the script modeled only the tagged producer's filename rule:

import { readFileSync } from "node:fs";
if (process.argv.includes("--version")) {
  console.log("sigrok-cli 0.7.2\nlibsigrokdecode 0.5.3");
} else {
  const name = process.argv
    .find(a => a.startsWith("--input-file=")).slice(13);
  console.log(JSON.stringify({
    name,
    reads_stdin: name === "-",
    observed_bytes: readFileSync(name === "-" ? 0 : name).length,
    private_copy_bytes: readFileSync(name).length
  }));
}

The final probe exited 0 and reproduced the filename-dependent routing once for each name; an earlier equivalent probe gave the same result. This does not establish real decoder annotations or its exit status.

For a real-provider reproduction, the proposed, unexecuted check is to copy an existing valid VCD to an absolute path ending in /- and submit the same request with the explicit VCD format. The source-derived path below establishes why the selected file is not opened.

Expected behavior

An admitted recording should reach sigrok through its private copy even when the source basename is -.

The tool contract accepts an existing local recording without this basename restriction. The recording guide promises decoding of a private, read-only copy.

Impact and scope

A recording named exactly - reaches the producer as empty stdin while the private copy exists and passes its integrity check. The observed control read 388 bytes; the failing selection read zero. Both source files remained unchanged, and all probe workspaces were removed.

Using an equivalent filename is an available workaround for the demonstrated routing failure. Actual sigrok annotations, diagnostics and exit status remain untested. No security impact is claimed.

REA version

Unreleased main revision 9066444f6b8e9ffe1607a9b02cde3895a37db431, manifest version 6.7.0.

Published rea-agents-6.7.0 at 27dc42d10249f0410904a75c0997842eb03b931c is unaffected: its provider uses the fixed private filename recording and passes --input-file=recording.

Runtime and platform

Node.js v26.12.1; Linux x86_64; repository-locked dependencies and tsx. The real sigrok executable and resource limiter were replaced by the explicitly described simulator.

Target and artifact context

Two identical, self-authored 388-byte UART VCD files; explicit VCD input format and UART selector. No hardware acquisition was involved.

Interface

Other

Earliest failure stage

Capture or observation

Relevant output or evidence

Observed boundary output, with unrelated fields omitted:

{"selected_basename":"control.vcd","source_bytes":388,"input_argument":"--input-file=control.vcd","observed":{"name":"control.vcd","reads_stdin":false,"observed_bytes":388,"private_copy_bytes":388}}
{"selected_basename":"-","source_bytes":388,"input_argument":"--input-file=-","observed":{"name":"-","reads_stdin":true,"observed_bytes":0,"private_copy_bytes":388}}
{"remaining_workspaces":[]}

Source-derived reachability:

  1. The CLI forwards the absolute selected path to the shared service.
  2. The provider reuses the source basename and passes it as the input operand.
  3. Sigrok-cli 0.7.2 tests for exactly -, selects fd 0 and skips opening that filename.
  4. REA's process launcher defaults stdin to ignore.

Evidence provenance: observed at the production command boundary; static for real sigrok's interpretation. Reproduction is complete for argument/input routing; real-provider decoding was not run.

Typed outcome or recovery expected

The producer should open the complete private recording for both filenames. A restoration check should use identical source bytes under both names and retain private-copy integrity checks, explicit format selection and cleanup.

Analysis or suspected cause

Source-derived: basename preservation forwards sigrok's reserved stdin operand as though it were an ordinary filename. The post-run digest check establishes that the private copy stayed intact, not that the producer consumed it. This is intentional sigrok argument behavior, not a sigrok defect.

Additional context

Related closed reports #6764, #6580 and #6733 concern oversized private names or lost autodetection hints. This report explicitly selects VCD and concerns the reserved stdin operand.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A valid filename deterministically changes the demonstrated producer input from the selected recording to empty stdin.
  • Workaround status: available
  • Workaround basis: Identical bytes under the control filename reached the producer intact; this establishes a routing workaround without asserting protocol-decoding results.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6839 ### 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 Evidence, artifacts, or reconstruction ### Observed behavior On unreleased main, `SignalRecordingService.decode` accepts an existing recording whose basename is `-`, copies it into its private workspace, and launches the producer with `--input-file=-`. Sigrok-cli 0.7.2 treats that operand as stdin. REA launches it with ignored stdin, so it receives an empty stream instead of the selected recording. Argument generation and input bytes were observed through the production service/provider with an inert command-boundary simulator. Real sigrok decoding and the CLI/MCP transports were not executed. Sigrok's interpretation is established from its tagged source. ### Reproduction The executed boundary probe created identical 388-byte UART VCD recordings named `control.vcd` and `-`, then called the production `SignalRecordingService` backed by `SigrokRecordingProvider` for each absolute path: ```js await service.decode({ path, decoders: "uart:rx=RX:baudrate=9600", input_format: "vcd", annotations: "uart=rx-data" }); ``` The probe used the production file reader, private runtime, process launcher, service validation and cleanup. Its injected launcher ran a Node script in place of sigrok/prlimit; the script modeled only the tagged producer's filename rule: ```js import { readFileSync } from "node:fs"; if (process.argv.includes("--version")) { console.log("sigrok-cli 0.7.2\nlibsigrokdecode 0.5.3"); } else { const name = process.argv .find(a => a.startsWith("--input-file=")).slice(13); console.log(JSON.stringify({ name, reads_stdin: name === "-", observed_bytes: readFileSync(name === "-" ? 0 : name).length, private_copy_bytes: readFileSync(name).length })); } ``` The final probe exited 0 and reproduced the filename-dependent routing once for each name; an earlier equivalent probe gave the same result. This does not establish real decoder annotations or its exit status. For a real-provider reproduction, the proposed, unexecuted check is to copy an existing valid VCD to an absolute path ending in `/-` and submit the same request with the explicit VCD format. The source-derived path below establishes why the selected file is not opened. ### Expected behavior An admitted recording should reach sigrok through its private copy even when the source basename is `-`. The [tool contract](https://github.com/morluto/rea/blob/9066444f6b8e9ffe1607a9b02cde3895a37db431/src/contracts/signals/signalToolContracts.ts#L34) accepts an existing local recording without this basename restriction. The [recording guide](https://github.com/morluto/rea/blob/9066444f6b8e9ffe1607a9b02cde3895a37db431/docs/signal-recordings.md#L85) promises decoding of a private, read-only copy. ### Impact and scope A recording named exactly `-` reaches the producer as empty stdin while the private copy exists and passes its integrity check. The observed control read 388 bytes; the failing selection read zero. Both source files remained unchanged, and all probe workspaces were removed. Using an equivalent filename is an available workaround for the demonstrated routing failure. Actual sigrok annotations, diagnostics and exit status remain untested. No security impact is claimed. ### REA version Unreleased main revision `9066444f6b8e9ffe1607a9b02cde3895a37db431`, manifest version `6.7.0`. Published `rea-agents-6.7.0` at `27dc42d10249f0410904a75c0997842eb03b931c` is unaffected: its provider uses the fixed private filename `recording` and passes `--input-file=recording`. ### Runtime and platform Node.js v26.12.1; Linux x86_64; repository-locked dependencies and tsx. The real sigrok executable and resource limiter were replaced by the explicitly described simulator. ### Target and artifact context Two identical, self-authored 388-byte UART VCD files; explicit VCD input format and UART selector. No hardware acquisition was involved. ### Interface Other ### Earliest failure stage Capture or observation ### Relevant output or evidence Observed boundary output, with unrelated fields omitted: ```json {"selected_basename":"control.vcd","source_bytes":388,"input_argument":"--input-file=control.vcd","observed":{"name":"control.vcd","reads_stdin":false,"observed_bytes":388,"private_copy_bytes":388}} {"selected_basename":"-","source_bytes":388,"input_argument":"--input-file=-","observed":{"name":"-","reads_stdin":true,"observed_bytes":0,"private_copy_bytes":388}} {"remaining_workspaces":[]} ``` Source-derived reachability: 1. [The CLI forwards the absolute selected path to the shared service](https://github.com/morluto/rea/blob/9066444f6b8e9ffe1607a9b02cde3895a37db431/src/cli/signalCommands.ts#L107). 2. [The provider reuses the source basename](https://github.com/morluto/rea/blob/9066444f6b8e9ffe1607a9b02cde3895a37db431/src/signals/SigrokRecordingProvider.ts#L182) and [passes it as the input operand](https://github.com/morluto/rea/blob/9066444f6b8e9ffe1607a9b02cde3895a37db431/src/signals/SigrokRecordingProvider.ts#L349). 3. [Sigrok-cli 0.7.2 tests for exactly `-`, selects fd 0 and skips opening that filename](https://github.com/sigrokproject/sigrok-cli/blob/sigrok-cli-0.7.2/input.c#L58). 4. [REA's process launcher defaults stdin to `ignore`](https://github.com/morluto/rea/blob/9066444f6b8e9ffe1607a9b02cde3895a37db431/src/process/ProviderProcess.ts#L294). Evidence provenance: observed at the production command boundary; static for real sigrok's interpretation. Reproduction is complete for argument/input routing; real-provider decoding was not run. ### Typed outcome or recovery expected The producer should open the complete private recording for both filenames. A restoration check should use identical source bytes under both names and retain private-copy integrity checks, explicit format selection and cleanup. ### Analysis or suspected cause Source-derived: basename preservation forwards sigrok's reserved stdin operand as though it were an ordinary filename. The post-run digest check establishes that the private copy stayed intact, not that the producer consumed it. This is intentional sigrok argument behavior, not a sigrok defect. ### Additional context Related closed reports [#6764](https://github.com/morluto/rea/issues/6764), [#6580](https://github.com/morluto/rea/issues/6580) and [#6733](https://github.com/morluto/rea/issues/6733) concern oversized private names or lost autodetection hints. This report explicitly selects VCD and concerns the reserved stdin operand. ### Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: A valid filename deterministically changes the demonstrated producer input from the selected recording to empty stdin. - Workaround status: available - Workaround basis: Identical bytes under the control filename reached the producer intact; this establishes a routing workaround without asserting protocol-decoding results.
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#4180
No description provided.