[GH-ISSUE #1774] [Bug] Windows: apktool launcher probe fails with spawn EINVAL when REA_APKTOOL_COMMAND points to a .cmd/.bat wrapper #597

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

Originally created by @psipher on GitHub (Oct 11, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/1774

Before submitting

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

Area

Setup, packaging, or upgrade

Observed behavior

On Windows x64, REA_APKTOOL_COMMAND pointed at a .cmd/.bat apktool launcher fails the version probe. The command reports a capability failure that blames the launcher rather than the spawn:

code: capability_unavailable
category: unsupported_provider
message: This analysis is unavailable for the current target.
details:
  provider_id: apktool
  reason: "The selected apktool launcher did not report a usable version"

Pointing the same variable at an .exe launcher resolves it immediately, with no other change.

Both inspect-apktool-client and decode-android-resources are affected.

Reproduction

On Windows x64, REA_APKTOOL_COMMAND pointed at a .cmd/.bat apktool launcher fails the version probe. The command reports a capability failure that blames the launcher rather than the spawn:

code: capability_unavailable
category: unsupported_provider
message: This analysis is unavailable for the current target.
details:
  provider_id: apktool
  reason: "The selected apktool launcher did not report a usable version"

Pointing the same variable at an .exe launcher resolves it immediately, with no other change.

Both inspect-apktool-client and decode-android-resources are affected.

Expected behavior

The launcher probe should accept the launcher forms the remediation text recommends. Setting
`REA_APKTOOL_COMMAND` to an absolute `.cmd`/`.bat` path should resolve the apktool version and
`inspect-apktool-client` should report `apktool_version: 3.0.3`.

If a launcher genuinely cannot be spawned, the error should distinguish that from an unparseable
version — for example by retaining the underlying `EINVAL`/`errno` in `details`, as the Ghidra and
JADX configuration paths do for their prerequisites — rather than reporting `version_unresolved`
for every non-ENOENT failure.

### Impact and scope

Setting `REA_APKTOOL_COMMAND` is the documented, only way to enable apktool resource decoding, and
the remediation text directs users to "the upstream wrapper or a `java -jar` script". On Windows the
upstream Chocolatey wrapper is `apktool.bat`, and `java -jar` launchers are normally `.cmd`/`.bat`
scripts — so both forms the remediation recommends are the forms that fail. Only a native `.exe`
launcher works, and nothing in the error output indicates that.

The scope is wider than apktool. `execFileOutput` is imported by 14 provider and runtime files,
including `dist/adb/AdbConfiguration.js`. Any provider configured with a `.cmd`/`.bat` launcher is
subject to the same spawn failure. `REA_ADB_PATH` only worked in my testing because the configured
`adb.exe` is a native binary.

Affected: `inspect-apktool-client` and `decode-android-resources` on Windows with a batch launcher;
same class of failure for any other provider pointed at a `.cmd`/`.bat`.

Not affected: native `.exe` launchers work. Non-Windows hosts are unaffected. Evidence integrity is
not implicated — no analysis runs, so no partial Evidence is produced.

### REA version

6.4.0 (npm install --global rea-agents)

### Runtime and platform

Node.js 26.4.0; Windows 11 x64; JDK Temurin 21.0.12.101; apktool 3.0.3 (Chocolatey); not applicable to Hopper/Ghidra

### Target and artifact context

APK: com.google.android.apps.youtube.vr.oculus 1.88.10 (116,959,503 bytes); not applicable — failure occurs during provider configuration, before any target is read

### Interface

CLI

### Earliest failure stage

Request parsing or validation

### Relevant output or evidence

```text
$ rea inspect-apktool-client
code: capability_unavailable
category: unsupported_provider
message: This analysis is unavailable for the current target. Choose another analysis or target.
retryable: false
details:
  provider_id: apktool
  operation: inspect_apktool_client
  reason: "The selected apktool launcher did not report a usable version"

Typed outcome or recovery expected

A typed configuration failure that names the spawn error rather than version_unresolved, e.g.
details.failure: "spawn_einval" with errno: -4071, so the caller can distinguish an unspawnable
launcher from a launcher that ran but returned unrecognised output.

Analysis or suspected cause

dist/apktool/ApktoolConfiguration.js:43 probes the launcher with
execFileOutput(selection.command, ["--version"], { ... }).

execFileOutput (dist/process/ExecFileOutput.js:71) calls execFile without shell: true. Its
own doc comment describes it as running "a shell-free command". Node's CVE-2024-27980 mitigation
blocks spawning .cmd/.bat files without a shell and throws EINVAL, so the script never runs.
ApktoolConfiguration.js:62 then reports version_unresolved for any non-ENOENT failure, hiding
the cause.

This is the same root cause as #504 / #505 / #526. #505 added a helper to route .cmd/.bat
candidates through cmd.exe /d /s /c with windowsVerbatimArguments: true. That helper
(windowsBatchCommand) is not present under that name in 6.4.0; equivalent batch handling exists in
three other paths but not in execFileOutput:

Path Batch handling
dist/application/ClientRegistrationIdentity.js:12 cmd.exe /d /c
dist/ghidra/GhidraLauncher.js:192-196 COMSPEC validation + quoteWindowsBatchToken
dist/process/capture/ProcessCaptureCapability.js:48 cmd.exe
dist/process/ExecFileOutput.js none

Possible fix: accept shell: true, or route through cmd.exe /d /s /c, for .cmd/.bat launchers
on win32 — in execFileOutput or at the apktool call site. Since execFileOutput is shared, a fix
there would cover every provider at once.

Additional context

Related: #504, #505, #526 (same root cause, runtime-toolchain probes), #1556 (added the apktool
provider).

Workaround: point REA_APKTOOL_COMMAND at a native .exe launcher instead of a .cmd/.bat
wrapper.

Originally created by @psipher on GitHub (Oct 11, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/1774 ### 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 Setup, packaging, or upgrade ### Observed behavior On Windows x64, `REA_APKTOOL_COMMAND` pointed at a `.cmd`/`.bat` apktool launcher fails the version probe. The command reports a capability failure that blames the launcher rather than the spawn: code: capability_unavailable category: unsupported_provider message: This analysis is unavailable for the current target. details: provider_id: apktool reason: "The selected apktool launcher did not report a usable version" Pointing the same variable at an `.exe` launcher resolves it immediately, with no other change. Both `inspect-apktool-client` and `decode-android-resources` are affected. ### Reproduction On Windows x64, `REA_APKTOOL_COMMAND` pointed at a `.cmd`/`.bat` apktool launcher fails the version probe. The command reports a capability failure that blames the launcher rather than the spawn: code: capability_unavailable category: unsupported_provider message: This analysis is unavailable for the current target. details: provider_id: apktool reason: "The selected apktool launcher did not report a usable version" Pointing the same variable at an `.exe` launcher resolves it immediately, with no other change. Both `inspect-apktool-client` and `decode-android-resources` are affected. ### Expected behavior ```markdown The launcher probe should accept the launcher forms the remediation text recommends. Setting `REA_APKTOOL_COMMAND` to an absolute `.cmd`/`.bat` path should resolve the apktool version and `inspect-apktool-client` should report `apktool_version: 3.0.3`. If a launcher genuinely cannot be spawned, the error should distinguish that from an unparseable version — for example by retaining the underlying `EINVAL`/`errno` in `details`, as the Ghidra and JADX configuration paths do for their prerequisites — rather than reporting `version_unresolved` for every non-ENOENT failure. ### Impact and scope Setting `REA_APKTOOL_COMMAND` is the documented, only way to enable apktool resource decoding, and the remediation text directs users to "the upstream wrapper or a `java -jar` script". On Windows the upstream Chocolatey wrapper is `apktool.bat`, and `java -jar` launchers are normally `.cmd`/`.bat` scripts — so both forms the remediation recommends are the forms that fail. Only a native `.exe` launcher works, and nothing in the error output indicates that. The scope is wider than apktool. `execFileOutput` is imported by 14 provider and runtime files, including `dist/adb/AdbConfiguration.js`. Any provider configured with a `.cmd`/`.bat` launcher is subject to the same spawn failure. `REA_ADB_PATH` only worked in my testing because the configured `adb.exe` is a native binary. Affected: `inspect-apktool-client` and `decode-android-resources` on Windows with a batch launcher; same class of failure for any other provider pointed at a `.cmd`/`.bat`. Not affected: native `.exe` launchers work. Non-Windows hosts are unaffected. Evidence integrity is not implicated — no analysis runs, so no partial Evidence is produced. ### REA version 6.4.0 (npm install --global rea-agents) ### Runtime and platform Node.js 26.4.0; Windows 11 x64; JDK Temurin 21.0.12.101; apktool 3.0.3 (Chocolatey); not applicable to Hopper/Ghidra ### Target and artifact context APK: com.google.android.apps.youtube.vr.oculus 1.88.10 (116,959,503 bytes); not applicable — failure occurs during provider configuration, before any target is read ### Interface CLI ### Earliest failure stage Request parsing or validation ### Relevant output or evidence ```text $ rea inspect-apktool-client code: capability_unavailable category: unsupported_provider message: This analysis is unavailable for the current target. Choose another analysis or target. retryable: false details: provider_id: apktool operation: inspect_apktool_client reason: "The selected apktool launcher did not report a usable version" ``` ### Typed outcome or recovery expected A typed configuration failure that names the spawn error rather than `version_unresolved`, e.g. `details.failure: "spawn_einval"` with `errno: -4071`, so the caller can distinguish an unspawnable launcher from a launcher that ran but returned unrecognised output. ### Analysis or suspected cause `dist/apktool/ApktoolConfiguration.js:43` probes the launcher with `execFileOutput(selection.command, ["--version"], { ... })`. `execFileOutput` (`dist/process/ExecFileOutput.js:71`) calls `execFile` without `shell: true`. Its own doc comment describes it as running "a shell-free command". Node's CVE-2024-27980 mitigation blocks spawning `.cmd`/`.bat` files without a shell and throws `EINVAL`, so the script never runs. `ApktoolConfiguration.js:62` then reports `version_unresolved` for any non-ENOENT failure, hiding the cause. This is the same root cause as #504 / #505 / #526. #505 added a helper to route `.cmd`/`.bat` candidates through `cmd.exe /d /s /c` with `windowsVerbatimArguments: true`. That helper (`windowsBatchCommand`) is not present under that name in 6.4.0; equivalent batch handling exists in three other paths but not in `execFileOutput`: | Path | Batch handling | | --- | --- | | `dist/application/ClientRegistrationIdentity.js:12` | `cmd.exe /d /c` | | `dist/ghidra/GhidraLauncher.js:192-196` | `COMSPEC` validation + `quoteWindowsBatchToken` | | `dist/process/capture/ProcessCaptureCapability.js:48` | `cmd.exe` | | `dist/process/ExecFileOutput.js` | none | Possible fix: accept `shell: true`, or route through `cmd.exe /d /s /c`, for `.cmd`/`.bat` launchers on `win32` — in `execFileOutput` or at the apktool call site. Since `execFileOutput` is shared, a fix there would cover every provider at once. ### Additional context Related: #504, #505, #526 (same root cause, runtime-toolchain probes), #1556 (added the apktool provider). Workaround: point `REA_APKTOOL_COMMAND` at a native `.exe` launcher instead of a `.cmd`/`.bat` wrapper.
bsakaguchi 2026-10-15 18:26:30 +00:00
  • closed this issue
  • added the
    triage
    bug
    labels
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#597
No description provided.