[GH-ISSUE #6757] [Bug] Empty CLI desktop path is silently replaced with the working directory #4115

Closed
opened 2026-10-31 00:46:55 +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/6757

Before submitting

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

Area

CLI

Observed behavior

Passing an empty positional path to inspect-desktop-application silently inspects the current working directory and exits 0. It returns the same Evidence ID as explicitly selecting .. The shared desktop inspection service rejects the empty path with invalid_request, so CLI path normalization changes a rejected selection into a successful inspection of another directory.

This was reproduced through the source CLI's createCli(...).serve(...) and createCliResultOutput boundaries. The packaged dispatcher was not built or tested.

Reproduction

  1. Create /tmp/desktop-fixture/marker.txt containing harmless text, and change the working directory to /tmp/desktop-fixture.
  2. Run the source CLI with argument vector:
    ["inspect-desktop-application", "", "--json"]
    
    The probe used createCliResultOutput(argv, destination) and createCli(process.env, output).serve(argv, { stdout, exit }), matching the executable's output adapter.
  3. Compare with ["inspect-desktop-application", ".", "--json"] and a direct createDesktopApplicationService().inspect({ path: "" }) call.
  4. Both CLI calls inspect marker.txt successfully and return the same Evidence ID. The direct shared-service call rejects path. One three-way reproduction was run, in an isolated temporary home and working directory.

Expected behavior

An empty path should fail input validation before resolution or directory inspection. Callers can explicitly pass . when they intend the current directory.

The shared desktop input schema requires a nonempty absolute local path. The CLI should preserve that selection contract while accepting relative paths.

Impact and scope

A shell invocation equivalent to rea inspect-desktop-application "$TARGET" --json, with an empty TARGET, can return successful Evidence for the working directory instead of reporting the missing selection. The observed consequence is a wrong target and successful status, not a target mutation. Explicit . worked as a control; validating that the supplied path is nonempty is a practical caller workaround.

Only this command and Linux were exercised. Other CLI commands using the same path-normalization helper were inspected but not runtime-tested for this behavior.

REA version

6.7.0 source, main 2bcd7e6d13f0a8118d6619718254255e84f75d86.

Runtime and platform

Node.js v24.22.1; Linux x64. No Hopper or Ghidra involved.

Target and artifact context

An isolated temporary directory containing one ordinary text file. No real application, external provider, or live service was used.

Interface

CLI

Earliest failure stage

Request parsing or validation

Relevant output or evidence

Reduced results from the executed probe; temporary paths are generalized:

CLI path "":  exit 0; operation inspect_desktop_application
              normalized_result.root.path = /tmp/desktop-fixture/
              normalized_result.files[].path = ["marker.txt"]
CLI path ".": exit 0; identical root, file list, and evidence_id
Shared service {path:""}: ok false; code invalid_request
  issues: path out_of_range minimum 1
          path invalid_format: must be an absolute local filesystem path

The probe, both complete CLI results, and the compact comparison report were retained locally for review. A built rea invocation and other operating systems remain untested.

Typed outcome or recovery expected

invalid_request identifying the empty path, with a nonzero CLI status and no directory inspection.

Analysis or suspected cause

Source-derived: the CLI argument uses z.string() without a minimum. It then calls absoluteCallerPath(args.path) before service validation. For "", that helper prefixes the working directory, so the shared schema receives a valid absolute directory instead of the caller's empty selection.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The local reproduction returned successful Evidence for the working directory when the caller selected an empty path, while the shared service rejected that selection. This can produce incorrect results in scripts with an empty path variable.
  • Workaround status: available
  • Workaround basis: The explicit . control selected the working directory successfully; callers can reject an empty variable before invoking the CLI and supply a nonempty intended path.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6757 ## 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 CLI ## Observed behavior Passing an empty positional path to `inspect-desktop-application` silently inspects the current working directory and exits 0. It returns the same Evidence ID as explicitly selecting `.`. The shared desktop inspection service rejects the empty path with `invalid_request`, so CLI path normalization changes a rejected selection into a successful inspection of another directory. This was reproduced through the source CLI's `createCli(...).serve(...)` and `createCliResultOutput` boundaries. The packaged dispatcher was not built or tested. ## Reproduction 1. Create `/tmp/desktop-fixture/marker.txt` containing harmless text, and change the working directory to `/tmp/desktop-fixture`. 2. Run the source CLI with argument vector: ```js ["inspect-desktop-application", "", "--json"] ``` The probe used `createCliResultOutput(argv, destination)` and `createCli(process.env, output).serve(argv, { stdout, exit })`, matching the executable's output adapter. 3. Compare with `["inspect-desktop-application", ".", "--json"]` and a direct `createDesktopApplicationService().inspect({ path: "" })` call. 4. Both CLI calls inspect `marker.txt` successfully and return the same Evidence ID. The direct shared-service call rejects `path`. One three-way reproduction was run, in an isolated temporary home and working directory. ## Expected behavior An empty path should fail input validation before resolution or directory inspection. Callers can explicitly pass `.` when they intend the current directory. The [shared desktop input schema](https://github.com/morluto/rea/blob/2bcd7e6d13f0a8118d6619718254255e84f75d86/src/domain/desktopApplication.ts#L18) requires a nonempty absolute local path. The CLI should preserve that selection contract while accepting relative paths. ## Impact and scope A shell invocation equivalent to `rea inspect-desktop-application "$TARGET" --json`, with an empty `TARGET`, can return successful Evidence for the working directory instead of reporting the missing selection. The observed consequence is a wrong target and successful status, not a target mutation. Explicit `.` worked as a control; validating that the supplied path is nonempty is a practical caller workaround. Only this command and Linux were exercised. Other CLI commands using the same path-normalization helper were inspected but not runtime-tested for this behavior. ## REA version 6.7.0 source, main `2bcd7e6d13f0a8118d6619718254255e84f75d86`. ## Runtime and platform Node.js v24.22.1; Linux x64. No Hopper or Ghidra involved. ## Target and artifact context An isolated temporary directory containing one ordinary text file. No real application, external provider, or live service was used. ## Interface CLI ## Earliest failure stage Request parsing or validation ## Relevant output or evidence Reduced results from the executed probe; temporary paths are generalized: ```text CLI path "": exit 0; operation inspect_desktop_application normalized_result.root.path = /tmp/desktop-fixture/ normalized_result.files[].path = ["marker.txt"] CLI path ".": exit 0; identical root, file list, and evidence_id Shared service {path:""}: ok false; code invalid_request issues: path out_of_range minimum 1 path invalid_format: must be an absolute local filesystem path ``` The probe, both complete CLI results, and the compact comparison report were retained locally for review. A built `rea` invocation and other operating systems remain untested. ## Typed outcome or recovery expected `invalid_request` identifying the empty `path`, with a nonzero CLI status and no directory inspection. ## Analysis or suspected cause Source-derived: the [CLI argument uses `z.string()` without a minimum](https://github.com/morluto/rea/blob/2bcd7e6d13f0a8118d6619718254255e84f75d86/src/cli/desktopApplicationCommands.ts#L22). It then [calls `absoluteCallerPath(args.path)` before service validation](https://github.com/morluto/rea/blob/2bcd7e6d13f0a8118d6619718254255e84f75d86/src/cli/desktopApplicationCommands.ts#L53). For `""`, [that helper prefixes the working directory](https://github.com/morluto/rea/blob/2bcd7e6d13f0a8118d6619718254255e84f75d86/src/filesystem/callerPath.ts#L20), so the shared schema receives a valid absolute directory instead of the caller's empty selection. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: The local reproduction returned successful Evidence for the working directory when the caller selected an empty path, while the shared service rejected that selection. This can produce incorrect results in scripts with an empty path variable. - Workaround status: available - Workaround basis: The explicit `.` control selected the working directory successfully; callers can reject an empty variable before invoking the CLI and supply a nonempty intended 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#4115
No description provided.