[GH-ISSUE #2577] fix(cli): file URLs become invented local paths in Electron requests #893

Closed
opened 2026-10-15 18:29:21 +00:00 by bsakaguchi · 0 comments
Owner

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

Summary

When capture-electron-scenario receives a file URL in executable_path, the CLI treats the URL as a relative filename and validates the resulting absolute path. A request with executable_path set to file:///opt/electron therefore reports that an invented local file does not exist, instead of explaining that the field requires a local filesystem path. This changes the caller's selected input and sends the caller toward correcting the wrong location.

Steps to reproduce

Use the source checkout and installed dependencies described under Runtime or environment on a POSIX host. Run from the repository root, with no file at the relative location file:/opt/electron. Save this test as src/cliFileUrlRegression.test.ts and run the focused command below. The fixture uses the existing current directory as the application path, so no Electron installation or target launch is required.

import { Cli } from "incur";
import pino from "pino";
import { expect, it } from "vitest";
import { registerElectronCommands } from "./cli/electronCommands.js";
import { resolveCliJsonPaths } from "./cliJsonInput.js";
import { electronActiveObservationInputSchema } from "./domain/javascript/electronActiveObservation.js";

it("rejects a file URL before treating it as a local path", async () => {
  const input = {
    executable_path: "file:///opt/electron",
    application_path: ".",
  };
  const normalized = resolveCliJsonPaths(input, [
    ["executable_path"], ["application_path"],
  ]);
  const cli = Cli.create("repro", { version: "1.0.0" });
  registerElectronCommands(cli, pino({ level: "silent" }), {});
  const output: string[] = [];
  const previousExitCode = process.exitCode;
  try {
    await cli.serve([
      "capture-electron-scenario", JSON.stringify(input), "--format", "json",
    ], { stdout: (text) => output.push(text), exit: () => {} });
    console.log(output.join(""));
    expect(electronActiveObservationInputSchema.safeParse(normalized).success)
      .toBe(false);
    expect(output.join(""))
      .toContain("must be absolute local filesystem paths");
  } finally {
    process.exitCode = previousExitCode;
  }
});
npm run test:focused -- src/cliFileUrlRegression.test.ts

Expected behavior

The CLI accepts ordinary relative filesystem paths and resolves them against the caller's working directory. A file URL supplied in an Electron filesystem-path field must remain distinguishable from a local path and receive a field-specific input error explaining the local-path requirement, before any filesystem lookup of an invented location.

Actual behavior

The verifier observed executable_path become an absolute path ending in /file:/opt/electron. Shared schema validation returned success for that rewritten input. Running the registered CLI command returned invalid_request with an executable_path issue, reason invalid_value, and a message reporting ENOENT while resolving the invented path. The input-rejection assertion failed. Ordinary relative and absolute path controls passed. The service rejected the nonexistent location before invoking provider.capture, so this observation does not establish an Electron launch.

Evidence

  • Expected source: AGENTS.md:29 distinguishes file URLs from local paths and preserves source identity; src/domain/javascript/electronActiveObservation.ts:6 and :68 define the applicable absolute-local-path requirement; src/cliJsonInput.ts:68 describes CLI normalization of operator-relative values.
  • Failure source: src/cliJsonInput.ts:94 resolves every selected nonblank string as a path; src/cli/electronCommands.ts:60 applies that transformation before validation; src/application/javascript/ElectronActiveObservationService.ts:23 and :87 perform the subsequent filesystem lookup and stop on its failure.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

The bounded verification ran the helper rejection assertion, the real registered CLI command through Cli.serve, and relative/absolute controls. One assertion failed and two checks passed. Sanitized observations were normalizedAccepted=true, cliCode=invalid_request, issueReason=invalid_value, and an ENOENT message containing file:/opt/electron. The raw schema also rejects a file URL when the other required path is absolute, as established by its isAbsolute refinement. A separate MCP transport replay was not run.

Related reports concern different contracts: CommonJS file URL dependency resolution was fixed in artifact relationship analysis, and Electron missing-path error attribution was fixed by reporting the correct failing field. Neither change prevents this CLI URL-to-path transformation.

Restoration check

For the same inline JSON, report the executable_path local-filesystem requirement without attempting to resolve a path ending in file:/opt/electron. The shared input boundary must not accept an invented absolute path derived from that URL. Keep the successful controls: bin/electron resolves against the working directory, /opt/electron stays unchanged, and blank path values remain invalid. These checks must not start an Electron process.

Runtime or environment

The failure was verified at source baseline a2d8b94dd5 and is still present at 8b181716ac, package version 6.4.0, Node v26.10.0, npm 11.19.1, Vitest v5.0.3, macOS POSIX path behavior, with dependencies already installed from the lockfile.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: File-URL inputs are silently reinterpreted as unrelated local locations, producing a misleading filesystem error. The observed failure is bounded to this input form; no process launch or data loss was observed.
  • Workaround status: available
  • Workaround basis: Supply a genuine local filesystem path. Focused controls confirmed ordinary relative CLI paths normalize correctly and absolute paths remain unchanged, preserving the selected location without a code change.
Originally created by @coygeek on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2577 ## Summary When capture-electron-scenario receives a file URL in executable_path, the CLI treats the URL as a relative filename and validates the resulting absolute path. A request with executable_path set to file:///opt/electron therefore reports that an invented local file does not exist, instead of explaining that the field requires a local filesystem path. This changes the caller's selected input and sends the caller toward correcting the wrong location. ## Steps to reproduce Use the source checkout and installed dependencies described under Runtime or environment on a POSIX host. Run from the repository root, with no file at the relative location file:/opt/electron. Save this test as src/cliFileUrlRegression.test.ts and run the focused command below. The fixture uses the existing current directory as the application path, so no Electron installation or target launch is required. ```ts import { Cli } from "incur"; import pino from "pino"; import { expect, it } from "vitest"; import { registerElectronCommands } from "./cli/electronCommands.js"; import { resolveCliJsonPaths } from "./cliJsonInput.js"; import { electronActiveObservationInputSchema } from "./domain/javascript/electronActiveObservation.js"; it("rejects a file URL before treating it as a local path", async () => { const input = { executable_path: "file:///opt/electron", application_path: ".", }; const normalized = resolveCliJsonPaths(input, [ ["executable_path"], ["application_path"], ]); const cli = Cli.create("repro", { version: "1.0.0" }); registerElectronCommands(cli, pino({ level: "silent" }), {}); const output: string[] = []; const previousExitCode = process.exitCode; try { await cli.serve([ "capture-electron-scenario", JSON.stringify(input), "--format", "json", ], { stdout: (text) => output.push(text), exit: () => {} }); console.log(output.join("")); expect(electronActiveObservationInputSchema.safeParse(normalized).success) .toBe(false); expect(output.join("")) .toContain("must be absolute local filesystem paths"); } finally { process.exitCode = previousExitCode; } }); ``` ```sh npm run test:focused -- src/cliFileUrlRegression.test.ts ``` ## Expected behavior The CLI accepts ordinary relative filesystem paths and resolves them against the caller's working directory. A file URL supplied in an Electron filesystem-path field must remain distinguishable from a local path and receive a field-specific input error explaining the local-path requirement, before any filesystem lookup of an invented location. ## Actual behavior The verifier observed executable_path become an absolute path ending in /file:/opt/electron. Shared schema validation returned success for that rewritten input. Running the registered CLI command returned invalid_request with an executable_path issue, reason invalid_value, and a message reporting ENOENT while resolving the invented path. The input-rejection assertion failed. Ordinary relative and absolute path controls passed. The service rejected the nonexistent location before invoking provider.capture, so this observation does not establish an Electron launch. ## Evidence - Expected source: AGENTS.md:29 distinguishes file URLs from local paths and preserves source identity; src/domain/javascript/electronActiveObservation.ts:6 and :68 define the applicable absolute-local-path requirement; src/cliJsonInput.ts:68 describes CLI normalization of operator-relative values. - Failure source: src/cliJsonInput.ts:94 resolves every selected nonblank string as a path; src/cli/electronCommands.ts:60 applies that transformation before validation; src/application/javascript/ElectronActiveObservationService.ts:23 and :87 perform the subsequent filesystem lookup and stop on its failure. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete The bounded verification ran the helper rejection assertion, the real registered CLI command through Cli.serve, and relative/absolute controls. One assertion failed and two checks passed. Sanitized observations were normalizedAccepted=true, cliCode=invalid_request, issueReason=invalid_value, and an ENOENT message containing file:/opt/electron. The raw schema also rejects a file URL when the other required path is absolute, as established by its isAbsolute refinement. A separate MCP transport replay was not run. Related reports concern different contracts: [CommonJS file URL dependency resolution](https://github.com/morluto/rea/issues/2057) was fixed in artifact relationship analysis, and [Electron missing-path error attribution](https://github.com/morluto/rea/issues/2272) was fixed by reporting the correct failing field. Neither change prevents this CLI URL-to-path transformation. ## Restoration check For the same inline JSON, report the executable_path local-filesystem requirement without attempting to resolve a path ending in file:/opt/electron. The shared input boundary must not accept an invented absolute path derived from that URL. Keep the successful controls: bin/electron resolves against the working directory, /opt/electron stays unchanged, and blank path values remain invalid. These checks must not start an Electron process. ## Runtime or environment The failure was verified at source baseline a2d8b94dd50dab8d966239dd63ab84718aa8b4b4 and is still present at 8b181716aca2cb467be499cba226abfb5ae19141, package version 6.4.0, Node v26.10.0, npm 11.19.1, Vitest v5.0.3, macOS POSIX path behavior, with dependencies already installed from the lockfile. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: File-URL inputs are silently reinterpreted as unrelated local locations, producing a misleading filesystem error. The observed failure is bounded to this input form; no process launch or data loss was observed. - Workaround status: available - Workaround basis: Supply a genuine local filesystem path. Focused controls confirmed ordinary relative CLI paths normalize correctly and absolute paths remain unchanged, preserving the selected location without a code change.
bsakaguchi 2026-10-15 18:29:21 +00:00
  • closed this issue
  • added the
    bug
    label
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#893
No description provided.