[GH-ISSUE #1188] [Bug] Opening an unreadable target returns target_unavailable instead of access_denied #422

Closed
opened 2026-10-15 18:24:55 +00:00 by bsakaguchi · 2 comments
Owner

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

Before submitting

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

Area

Native analysis or decompilation

Observed behavior

Opening an existing executable that the current user cannot read returns target_unavailable instead of access_denied through both CLI and MCP. The diagnostic text contains EACCES, but the machine-readable code identifies the failure as generic target unavailability. Clients that branch on the documented error code cannot distinguish an OS read-permission failure from a missing target.

Both CLI runs exited 1. Both MCP calls returned isError: true with this meaningful projection, with local paths normalized here:

{
  "code": "target_unavailable",
  "category": "unavailable",
  "retryable": false,
  "message": "Cannot open artifact: permission denied while reading target: EACCES: permission denied, access '/absolute/path/to/unreadable'. Check that the path exists, is readable, and points to a supported file.",
  "details": {
    "path": "/absolute/path/to/unreadable",
    "reason": "permission denied while reading target: EACCES: permission denied, access '/absolute/path/to/unreadable'"
  }
}

The failure happens during target admission, before the provider starts. parseBinaryTarget catches the filesystem error and constructs BinaryTargetError; its fixed public projection is target_unavailable. The readable control opens successfully with provider_id: "ghidra".

Reproduction

Use the baselines under Runtime or environment and an ordinary non-root account. Configure the existing Ghidra installation and JDK, then run these commands from a disposable directory outside the REA checkout:

export GHIDRA_INSTALL_DIR=/path/to/ghidra_12.1.4_PUBLIC
export JAVA_HOME=/path/to/jdk-21
export REA_MAIN=/path/to/rea-main
cat > fixture.c <<'EOF'
int main(void) { return 0; }
EOF
clang -g -O0 fixture.c -o fixture
cp fixture unreadable
chmod 000 unreadable
npx -y rea-agents@6.1.0 analyze "$PWD/unreadable" --provider ghidra --json
node "$REA_MAIN/scripts/rea.mjs" analyze "$PWD/unreadable" --provider ghidra --json

For MCP, initialize npx -y rea-agents@6.1.0 mcp or node "$REA_MAIN/scripts/rea.mjs" mcp with the same environment and call open_binary with {"path":"/absolute/path/to/unreadable","provider_id":"ghidra"}. Both entry points were executed. A readable copy of the same executable is the control; opening it succeeds. Restore the disposable file with chmod 600 unreadable after the probe.

Expected behavior

The failed constraint is host filesystem read permission. Return access_denied, preserve the selected path and EACCES or EPERM, and provide advice that addresses read access. The repository's Boundary Contracts explicitly distinguish host OS permission denial from malformed input, unsupported targets, and unavailable providers. The existing AnalysisAccessDeniedError public projection supplies this code for a denied selected read.

Impact and scope

The machine-readable result misclassifies a real OS read denial through both supported entry points, preventing clients from selecting permission-specific recovery by error code. The file is not modified and normal readable inputs still work. Impact assessment: P2 (supported).

Workaround (available): The returned diagnostic text includes EACCES; an operator can inspect that reason and restore read access or select a readable copy. The readable-copy control was observed to open successfully.

REA version

rea-agents@6.1.0 from npm, and main at b34bdcdb28 built locally with npm ci && npm run build:cached.

Runtime and platform

Tested against npm rea-agents@6.1.0 and the current main build at b34bdcdb2877be394c59c9cbf70269dc1841ff78, with Ghidra 12.1.4, Homebrew OpenJDK 21.0.12.1, Node 24.21.0, and macOS 27 arm64. The executing account was non-root, and the control was a clang-built thin arm64 Mach-O executable.

Target and artifact context

Thin arm64 Mach-O C executable with mode 000 (Ghidra provider)

Interface

CLI

Earliest failure stage

Request parsing or validation

Relevant output or evidence

  • Expected source: AGENTS.md, Boundary Contracts, paragraph beginning "Preserve meaningful failure reasons"; src/domain/analysisErrorCore.ts:132, selected host-read denial; src/domain/analysisErrorProjection.ts:176, AnalysisAccessDeniedError: "access_denied"; docs/error-contract.schema.json, access_denied branch; docs/native-investigation.md:168, "On Linux and macOS, an unreadable source reports access_denied" for the Ghidra source copy.
  • Failure source: The CLI commands and MCP open_binary request above, executed against both tested builds, returned the inline target_unavailable projection. src/application/BinaryTargetResolver.ts:115 wraps EACCES in BinaryTargetError; src/domain/analysisErrorProjection.ts:189 assigns that tag target_unavailable.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

Typed outcome or recovery expected

Repeat the CLI and MCP probes as a non-root account against the unreadable existing executable. Both must return access_denied with the failed read constraint and selected path. Restore read permission and confirm the same bytes open normally. Keep a missing-path control distinguishable from permission denial, and confirm no Ghidra process or project starts for the denied read.

Analysis or suspected cause

No response

Additional context

No response

Originally created by @coygeek on GitHub (Oct 9, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/1188 ### 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 Native analysis or decompilation ### Observed behavior Opening an existing executable that the current user cannot read returns `target_unavailable` instead of `access_denied` through both CLI and MCP. The diagnostic text contains `EACCES`, but the machine-readable code identifies the failure as generic target unavailability. Clients that branch on the documented error code cannot distinguish an OS read-permission failure from a missing target. Both CLI runs exited 1. Both MCP calls returned `isError: true` with this meaningful projection, with local paths normalized here: ```json { "code": "target_unavailable", "category": "unavailable", "retryable": false, "message": "Cannot open artifact: permission denied while reading target: EACCES: permission denied, access '/absolute/path/to/unreadable'. Check that the path exists, is readable, and points to a supported file.", "details": { "path": "/absolute/path/to/unreadable", "reason": "permission denied while reading target: EACCES: permission denied, access '/absolute/path/to/unreadable'" } } ``` The failure happens during target admission, before the provider starts. `parseBinaryTarget` catches the filesystem error and constructs `BinaryTargetError`; its fixed public projection is `target_unavailable`. The readable control opens successfully with `provider_id: "ghidra"`. ### Reproduction Use the baselines under Runtime or environment and an ordinary non-root account. Configure the existing Ghidra installation and JDK, then run these commands from a disposable directory outside the REA checkout: ```sh export GHIDRA_INSTALL_DIR=/path/to/ghidra_12.1.4_PUBLIC export JAVA_HOME=/path/to/jdk-21 export REA_MAIN=/path/to/rea-main cat > fixture.c <<'EOF' int main(void) { return 0; } EOF clang -g -O0 fixture.c -o fixture cp fixture unreadable chmod 000 unreadable npx -y rea-agents@6.1.0 analyze "$PWD/unreadable" --provider ghidra --json node "$REA_MAIN/scripts/rea.mjs" analyze "$PWD/unreadable" --provider ghidra --json ``` For MCP, initialize `npx -y rea-agents@6.1.0 mcp` or `node "$REA_MAIN/scripts/rea.mjs" mcp` with the same environment and call `open_binary` with `{"path":"/absolute/path/to/unreadable","provider_id":"ghidra"}`. Both entry points were executed. A readable copy of the same executable is the control; opening it succeeds. Restore the disposable file with `chmod 600 unreadable` after the probe. ### Expected behavior The failed constraint is host filesystem read permission. Return `access_denied`, preserve the selected path and `EACCES` or `EPERM`, and provide advice that addresses read access. The repository's Boundary Contracts explicitly distinguish host OS permission denial from malformed input, unsupported targets, and unavailable providers. The existing `AnalysisAccessDeniedError` public projection supplies this code for a denied selected read. ### Impact and scope The machine-readable result misclassifies a real OS read denial through both supported entry points, preventing clients from selecting permission-specific recovery by error code. The file is not modified and normal readable inputs still work. Impact assessment: P2 (supported). Workaround (available): The returned diagnostic text includes `EACCES`; an operator can inspect that reason and restore read access or select a readable copy. The readable-copy control was observed to open successfully. ### REA version `rea-agents@6.1.0` from npm, and `main` at b34bdcdb2877be394c59c9cbf70269dc1841ff78 built locally with `npm ci && npm run build:cached`. ### Runtime and platform Tested against npm `rea-agents@6.1.0` and the current main build at `b34bdcdb2877be394c59c9cbf70269dc1841ff78`, with Ghidra 12.1.4, Homebrew OpenJDK 21.0.12.1, Node 24.21.0, and macOS 27 arm64. The executing account was non-root, and the control was a clang-built thin arm64 Mach-O executable. ### Target and artifact context Thin arm64 Mach-O C executable with mode 000 (Ghidra provider) ### Interface CLI ### Earliest failure stage Request parsing or validation ### Relevant output or evidence - Expected source: `AGENTS.md`, Boundary Contracts, paragraph beginning "Preserve meaningful failure reasons"; `src/domain/analysisErrorCore.ts:132`, selected host-read denial; `src/domain/analysisErrorProjection.ts:176`, `AnalysisAccessDeniedError: "access_denied"`; `docs/error-contract.schema.json`, `access_denied` branch; `docs/native-investigation.md:168`, "On Linux and macOS, an unreadable source reports `access_denied`" for the Ghidra source copy. - Failure source: The CLI commands and MCP `open_binary` request above, executed against both tested builds, returned the inline `target_unavailable` projection. `src/application/BinaryTargetResolver.ts:115` wraps `EACCES` in `BinaryTargetError`; `src/domain/analysisErrorProjection.ts:189` assigns that tag `target_unavailable`. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete ### Typed outcome or recovery expected Repeat the CLI and MCP probes as a non-root account against the unreadable existing executable. Both must return `access_denied` with the failed read constraint and selected path. Restore read permission and confirm the same bytes open normally. Keep a missing-path control distinguishable from permission denial, and confirm no Ghidra process or project starts for the denied read. ### Analysis or suspected cause _No response_ ### Additional context _No response_
bsakaguchi 2026-10-15 18:24:55 +00:00
Author
Owner

@Sravan1011 commented on GitHub (Oct 9, 2026):

@coygeek I'll take this one

<!-- gh-comment-id:6073937842 --> @Sravan1011 commented on GitHub (Oct 9, 2026): @coygeek I'll take this one
Author
Owner

@Sravan1011 commented on GitHub (Oct 9, 2026):

@kaoru0822-kitauji I was working on this man, if you are workring just comment on it

<!-- gh-comment-id:6073982469 --> @Sravan1011 commented on GitHub (Oct 9, 2026): @kaoru0822-kitauji I was working on this man, if you are workring just comment on it
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#422
No description provided.