[PR #3511] [MERGED] fix(cli): route app bundles with trailing separators to native analysis #5791

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/3511
Author: @Sriram-PR
Created: 10/14/2026
Status: ✅ Merged
Merged: 10/15/2026
Merged by: @baron

Base: main ← Head: fix/analyze-app-bundle-trailing-separator


📝 Commits (1)

  • b5dbc93 fix(cli): route app bundles with trailing separators to native analysis

📊 Changes

2 files changed (+54 additions, -1 deletions)

View changed files

📝 src/cli/coreBinaryCommands.ts (+2 -1)
➕ tests/boundary/cli/analyzeAppBundlePathCli.test.ts (+52 -0)

📄 Description

Summary

analyze sample.app/ and analyze sample.app/. ran static JavaScript application analysis on a native macOS app bundle instead of native analysis. The routing check in isJavaScriptApplicationPath tested path.toLowerCase().endsWith(".app") on the raw argument, so a trailing / (what shell completion gives you) or /. missed it and fell through to the "any directory is a JavaScript app" branch. The command then exited 0 with an analyze_javascript_application result over zero source files.

Fixes #3321

Problem and expected behavior

Smallest trigger: a Sample.app bundle with Contents/Info.plist and a Mach-O Contents/MacOS/Sample, REA_ANALYSIS_PROVIDER=missing-provider. analyze Sample.app exits 1 with capability_unavailable from native provider selection; analyze Sample.app/ and analyze Sample.app/. exit 0 with JavaScript application Evidence. Expected: all spellings of the same bundle take the native path (docs/cli.md: directly supplied .app bundles get the native overview).

Change and scope

  • src/cli/coreBinaryCommands.ts: the .app check now ignores trailing / and /. segments before matching the extension. Everything downstream already handled those spellings: forcing the native route with --provider gave the same result for all three on the base revision.
  • Only the .app check changes. .asar matching and the directory fallback are as before, so JavaScript directories with or without a trailing slash still route to JavaScript analysis.
  • Not included: .. segments. Sample.app/x/.. is left alone on purpose; resolving it lexically could pick a different bundle when x is a symlink.

Contribution scope: ordinary fix within existing boundaries; no scope decision needed.

Contract and boundary impact

  • Semantic owner and earliest changed stage: isJavaScriptApplicationPath in src/cli/coreBinaryCommands.ts, when analyze picks its workflow.
  • Contribution scope fit and linked maintainer decision: not applicable (bug fix, #3321).
  • CLI and MCP/tool-catalog contract: no schema change. analyze <bundle>.app/ now returns native analysis results (or native provider errors) instead of JavaScript application Evidence. MCP is not affected; this routing is CLI-only.
  • Provider, bridge, target-format, or platform compatibility: none.
  • Evidence, artifact, provenance, or reconstruction contract: none beyond the routing; the native path receives the argument unchanged.
  • Target selection, authority, upstream behavior, and cleanup details: the selected bundle is the same; only the workflow chosen for it changes.
  • Generated metadata, package, or installation impact: none.

Expected effects (check known effects; use documentation-only on its own).
Unchecked items do not establish absence; leave uncertainties visible.

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Tests added or updated: tests/boundary/cli/analyzeAppBundlePathCli.test.ts runs analyze on Sample.app, Sample.app/, Sample.app/. and Sample.app// with an unknown standing provider and expects capability_unavailable from open_binary with selection_reason: unknown_provider for each.
  • Base reproduction: on the base revision the three trailing spellings fail with expected +0 to be 1 (exit 0 on the JavaScript route); the plain spelling passes.
  • User-visible CLI output (REA_ANALYSIS_PROVIDER=missing-provider analyze <path> --json, fixture from the issue, plus a plain jsapp/index.js directory as a control):
    path          base                                       PR
    sample.app    exit 1 capability_unavailable open_binary  exit 1 capability_unavailable open_binary
    sample.app/   exit 0 analyze_javascript_application      exit 1 capability_unavailable open_binary
    sample.app/.  exit 0 analyze_javascript_application      exit 1 capability_unavailable open_binary
    jsapp         exit 0 analyze_javascript_application      exit 0 analyze_javascript_application
    jsapp/        exit 0 analyze_javascript_application      exit 0 analyze_javascript_application
    
  • Remaining proof gaps: Linux x64 only; no real Ghidra/Hopper/IDA run, since the change is in workflow selection before any provider starts.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • npm run test:focused -- tests/boundary/cli/analyzeAppBundlePathCli.test.ts: 4 passed (3 fail on the base revision)
  • npm run test:focused on the 9 CLI boundary test files that run analyze (grep -l '"analyze"' tests/boundary/cli/*.test.ts): 58 passed, 1 skipped
  • npm run check:fast: typecheck and lint passed
  • CLI comparison above, built with npm run build:cached on base and on this branch

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Callers who relied on analyze X.app/ producing JavaScript Evidence now get native analysis; analyze-javascript-application (or passing the bundle's JavaScript directory) still selects JavaScript analysis explicitly.
  • Real Hopper/Ghidra, browser, or OS coverage: Linux x64, Node 24.18.0; macOS and Windows not run.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: none; no new filesystem access.

Author readiness

Human owner: @Sriram-PR

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

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.

🔄 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/3511 **Author:** [@Sriram-PR](https://github.com/Sriram-PR) **Created:** 10/14/2026 **Status:** ✅ Merged **Merged:** 10/15/2026 **Merged by:** [@baron](https://github.com/baron) **Base:** `main` ← **Head:** `fix/analyze-app-bundle-trailing-separator` --- ### 📝 Commits (1) - [`b5dbc93`](https://github.com/morluto/rea/commit/b5dbc933dbe18122b78c5fe32e1ff5309f4e037b) fix(cli): route app bundles with trailing separators to native analysis ### 📊 Changes **2 files changed** (+54 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `src/cli/coreBinaryCommands.ts` (+2 -1) ➕ `tests/boundary/cli/analyzeAppBundlePathCli.test.ts` (+52 -0) </details> ### 📄 Description ## Summary `analyze sample.app/` and `analyze sample.app/.` ran static JavaScript application analysis on a native macOS app bundle instead of native analysis. The routing check in `isJavaScriptApplicationPath` tested `path.toLowerCase().endsWith(".app")` on the raw argument, so a trailing `/` (what shell completion gives you) or `/.` missed it and fell through to the "any directory is a JavaScript app" branch. The command then exited 0 with an `analyze_javascript_application` result over zero source files. Fixes #3321 ## Problem and expected behavior Smallest trigger: a `Sample.app` bundle with `Contents/Info.plist` and a Mach-O `Contents/MacOS/Sample`, `REA_ANALYSIS_PROVIDER=missing-provider`. `analyze Sample.app` exits 1 with `capability_unavailable` from native provider selection; `analyze Sample.app/` and `analyze Sample.app/.` exit 0 with JavaScript application Evidence. Expected: all spellings of the same bundle take the native path (docs/cli.md: directly supplied `.app` bundles get the native overview). ## Change and scope - `src/cli/coreBinaryCommands.ts`: the `.app` check now ignores trailing `/` and `/.` segments before matching the extension. Everything downstream already handled those spellings: forcing the native route with `--provider` gave the same result for all three on the base revision. - Only the `.app` check changes. `.asar` matching and the directory fallback are as before, so JavaScript directories with or without a trailing slash still route to JavaScript analysis. - Not included: `..` segments. `Sample.app/x/..` is left alone on purpose; resolving it lexically could pick a different bundle when `x` is a symlink. Contribution scope: ordinary fix within existing boundaries; no scope decision needed. ## Contract and boundary impact - Semantic owner and earliest changed stage: `isJavaScriptApplicationPath` in `src/cli/coreBinaryCommands.ts`, when `analyze` picks its workflow. - Contribution scope fit and linked maintainer decision: not applicable (bug fix, #3321). - CLI and MCP/tool-catalog contract: no schema change. `analyze <bundle>.app/` now returns native analysis results (or native provider errors) instead of JavaScript application Evidence. MCP is not affected; this routing is CLI-only. - Provider, bridge, target-format, or platform compatibility: none. - Evidence, artifact, provenance, or reconstruction contract: none beyond the routing; the native path receives the argument unchanged. - Target selection, authority, upstream behavior, and cleanup details: the selected bundle is the same; only the workflow chosen for it changes. - Generated metadata, package, or installation impact: none. Expected effects (check known effects; use documentation-only on its own). Unchecked items do not establish absence; leave uncertainties visible. - [x] Read existing files or captured data. - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - Tests added or updated: `tests/boundary/cli/analyzeAppBundlePathCli.test.ts` runs `analyze` on `Sample.app`, `Sample.app/`, `Sample.app/.` and `Sample.app//` with an unknown standing provider and expects `capability_unavailable` from `open_binary` with `selection_reason: unknown_provider` for each. - Base reproduction: on the base revision the three trailing spellings fail with `expected +0 to be 1` (exit 0 on the JavaScript route); the plain spelling passes. - User-visible CLI output (`REA_ANALYSIS_PROVIDER=missing-provider analyze <path> --json`, fixture from the issue, plus a plain `jsapp/index.js` directory as a control): ``` path base PR sample.app exit 1 capability_unavailable open_binary exit 1 capability_unavailable open_binary sample.app/ exit 0 analyze_javascript_application exit 1 capability_unavailable open_binary sample.app/. exit 0 analyze_javascript_application exit 1 capability_unavailable open_binary jsapp exit 0 analyze_javascript_application exit 0 analyze_javascript_application jsapp/ exit 0 analyze_javascript_application exit 0 analyze_javascript_application ``` - Remaining proof gaps: Linux x64 only; no real Ghidra/Hopper/IDA run, since the change is in workflow selection before any provider starts. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `npm run test:focused -- tests/boundary/cli/analyzeAppBundlePathCli.test.ts`: 4 passed (3 fail on the base revision) - `npm run test:focused` on the 9 CLI boundary test files that run `analyze` (`grep -l '"analyze"' tests/boundary/cli/*.test.ts`): 58 passed, 1 skipped - `npm run check:fast`: typecheck and lint passed - CLI comparison above, built with `npm run build:cached` on base and on this branch ## Compatibility, safety, and release - Breaking changes or migration steps: none. Callers who relied on `analyze X.app/` producing JavaScript Evidence now get native analysis; `analyze-javascript-application` (or passing the bundle's JavaScript directory) still selects JavaScript analysis explicitly. - Real Hopper/Ghidra, browser, or OS coverage: Linux x64, Node 24.18.0; macOS and Windows not run. - Package or release metadata impact: none. - Security, privacy, process, or containment review: none; no new filesystem access. ## Author readiness Human owner: @Sriram-PR - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## 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. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:09:28 +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#5791
No description provided.