[GH-ISSUE #3187] [Bug] Signature inspection guidance refers to a debugger-attach facet absent from results #1125

Closed
opened 2026-10-15 18:31:17 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

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

Area

Documentation

Observed behavior

The native investigation guide says inspect_signature reports a debugger-attach facet, and the debugger-denial remediation directs callers to it. The real inspect-signature CLI returned successful native-macos Evidence for a hardened-runtime Mach-O without the debugging entitlement, a hardened-runtime control with the entitlement, and an unsigned control. None of their normalized_result objects contained that facet.

The operation returned the underlying signing facts correctly in these reproductions. The hardened target without entitlements returned signed: true, hardened_runtime: true, and entitlements: null. The entitlement-bearing control returned hardened_runtime: true and entitlements: {"com.apple.security.get-task-allow": true}. The unsigned control returned signed: false, hardened_runtime: null, and entitlements: null. The defect is the guidance about where to find the stated result.

Reproduction

Use a clean checkout at 58300885207133422af235e0f2b10658cf958b03 on macOS arm64 with Xcode Command Line Tools available. Run these steps from the repository root. Dependency installation and the build prepare a clean checkout; the verifier exercised the reproduction against an already installed and built checkout.

  1. Install dependencies and build the runtime.

    npm ci
    npm run build:cached
    
  2. Create a local C fixture, compile it, and sign it with hardened runtime and no debugging entitlement. The per-command environment isolates REA configuration and cache data.

    set -eu
    mkdir -p .repro-signature/home/config .repro-signature/home/cache .repro-signature/home/data
    cat > .repro-signature/target.c <<'EOF'
    int main(void) { return 0; }
    EOF
    xcrun clang .repro-signature/target.c -o .repro-signature/hardened-no-entitlement
    codesign --force --sign - --options runtime --identifier local.repro.denied .repro-signature/hardened-no-entitlement
    env HOME="$PWD/.repro-signature/home" \
      XDG_CONFIG_HOME="$PWD/.repro-signature/home/config" \
      XDG_CACHE_HOME="$PWD/.repro-signature/home/cache" \
      XDG_DATA_HOME="$PWD/.repro-signature/home/data" \
      node scripts/rea.mjs inspect-signature .repro-signature/hardened-no-entitlement --format json > .repro-signature/hardened-no-entitlement.json
    
  3. Create an entitlement-bearing control and an unsigned control, then inspect both.

    cp .repro-signature/hardened-no-entitlement .repro-signature/hardened-with-entitlement
    cat > .repro-signature/entitlements.plist <<'EOF'
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0"><dict><key>com.apple.security.get-task-allow</key><true/></dict></plist>
    EOF
    codesign --force --sign - --options runtime --identifier local.repro.allowed --entitlements .repro-signature/entitlements.plist .repro-signature/hardened-with-entitlement
    cp .repro-signature/hardened-no-entitlement .repro-signature/unsigned
    codesign --remove-signature .repro-signature/unsigned
    for target in hardened-with-entitlement unsigned; do
      env HOME="$PWD/.repro-signature/home" \
        XDG_CONFIG_HOME="$PWD/.repro-signature/home/config" \
        XDG_CACHE_HOME="$PWD/.repro-signature/home/cache" \
        XDG_DATA_HOME="$PWD/.repro-signature/home/data" \
        node scripts/rea.mjs inspect-signature ".repro-signature/$target" --format json > ".repro-signature/$target.json"
    done
    
  4. Print the returned signing facts and the complete key sets. Compare them with docs/native-investigation.md:482-485 and the remediation in src/native/LldbCallTracer.ts:165-166.

    node --input-type=module <<'EOF'
    import { readFileSync } from 'node:fs';
    for (const target of ['hardened-no-entitlement', 'hardened-with-entitlement', 'unsigned']) {
      const evidence = JSON.parse(readFileSync(`.repro-signature/${target}.json`, 'utf8'));
      const result = evidence.normalized_result;
      console.log(JSON.stringify({target, provider: evidence.provider.id, signed: result.signed, hardened_runtime: result.hardened_runtime, entitlements: result.entitlements, keys: Object.keys(result)}));
    }
    EOF
    

Expected behavior

docs/native-investigation.md:482-485 states that inspect_signature reports the missing debugging entitlement on a hardened-runtime target as a debugger-attach facet. src/native/LldbCallTracer.ts:165-166 also directs callers to that facet. Following this guidance should identify an actual returned value or accurately explain how to read the existing signing facts.

Accurate guidance about hardened_runtime and nullable entitlements is sufficient to resolve this wording defect; adding a separate derived field is not the only acceptable repair. Signing prerequisites alone must not become a guarantee that Developer Tools permission or every other debugger requirement is satisfied.

Impact and scope

P3, supported. Two caller-facing instructions name a nonexistent result facet, while the reproduced signature inspections complete and preserve the underlying signing facts. Callers can inspect hardened_runtime and raw entitlements directly, handling entitlements: null as well as an entitlement object. No loss of signing results or debugger enforcement failure was demonstrated.

The verifier exercised the actual CLI with local compiler and signing tools and no provider fakes. Debugger launch and the debugger-attach-denied error itself were not exercised. This report makes no claim that either is broken or that MCP runtime behavior was reproduced.

REA version

6.4.0 (main at 5830088520)

Runtime and platform

Node.js v26.10.0; macOS 27.0.1, build 26A434; arm64. Apple's local compiler and codesign were used. Hopper, Ghidra and LLDB are not required for signature inspection.

Target and artifact context

Locally compiled Mach-O arm64 executable containing int main(void) { return 0; }, with three variants: ad hoc signed with hardened runtime and no entitlements, ad hoc signed with hardened runtime and com.apple.security.get-task-allow: true, and unsigned. Each inspection returns native-macos Evidence.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

provider: native-macos
hardened-no-entitlement: signed=true, hardened_runtime=true, entitlements=null
hardened-with-entitlement: signed=true, hardened_runtime=true, entitlements={"com.apple.security.get-task-allow":true}
unsigned: signed=false, hardened_runtime=null, entitlements=null

All three normalized_result key sets:
signed, identifier, team_identifier, format, cdhashes, hash_algorithms,
authorities, designated_requirement, entitlements, timestamp,
hardened_runtime, provenance, limitations

No debugger-attach facet appears in any result.

Typed outcome or recovery expected

Repeat the three inspections and follow the revised guide and denial remediation. Both instructions should accurately identify returned signing information, either through the existing hardened-runtime and entitlement facts with null handling or through a facet the operation actually returns. The entitlement-bearing control must remain distinguishable from the target without entitlements, and the unsigned control must retain its explicit unknown hardened-runtime state. The guidance must keep signing prerequisites separate from overall debugger access.

Analysis or suspected cause

Source-derived at baseline 58300885207133422af235e0f2b10658cf958b03: docs/native-investigation.md:482-485 and src/native/LldbCallTracer.ts:165-166 name the absent facet. src/domain/native/nativeInspection.ts:146-160 defines the thirteen returned fields, and src/native/NativeMacOSProvider.ts:598-673 constructs the result from codesign output and raw entitlements. These source definitions agree with the independently reproduced CLI key sets. The narrower tool description at src/contracts/native/nativeToolContracts.ts:106-109 promises raw signing identity, entitlements and hardened-runtime state rather than a separate facet.

Additional context

Related: #934 proposed a broader signing-posture feature and closed without merging, #964 repeats the facet wording in its LLDB feature description, #2156 tracks other documentation findings, and #2397 investigates actual LLDB runtime failures; this report concerns only the inaccurate guide/remediation reference demonstrated by successful signature-inspection results.

Originally created by @coygeek on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3187 ### 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 Documentation ### Observed behavior The native investigation guide says `inspect_signature` reports a debugger-attach facet, and the debugger-denial remediation directs callers to it. The real `inspect-signature` CLI returned successful `native-macos` Evidence for a hardened-runtime Mach-O without the debugging entitlement, a hardened-runtime control with the entitlement, and an unsigned control. None of their `normalized_result` objects contained that facet. The operation returned the underlying signing facts correctly in these reproductions. The hardened target without entitlements returned `signed: true`, `hardened_runtime: true`, and `entitlements: null`. The entitlement-bearing control returned `hardened_runtime: true` and `entitlements: {"com.apple.security.get-task-allow": true}`. The unsigned control returned `signed: false`, `hardened_runtime: null`, and `entitlements: null`. The defect is the guidance about where to find the stated result. ### Reproduction Use a clean checkout at `58300885207133422af235e0f2b10658cf958b03` on macOS arm64 with Xcode Command Line Tools available. Run these steps from the repository root. Dependency installation and the build prepare a clean checkout; the verifier exercised the reproduction against an already installed and built checkout. 1. Install dependencies and build the runtime. ```sh npm ci npm run build:cached ``` 2. Create a local C fixture, compile it, and sign it with hardened runtime and no debugging entitlement. The per-command environment isolates REA configuration and cache data. ```sh set -eu mkdir -p .repro-signature/home/config .repro-signature/home/cache .repro-signature/home/data cat > .repro-signature/target.c <<'EOF' int main(void) { return 0; } EOF xcrun clang .repro-signature/target.c -o .repro-signature/hardened-no-entitlement codesign --force --sign - --options runtime --identifier local.repro.denied .repro-signature/hardened-no-entitlement env HOME="$PWD/.repro-signature/home" \ XDG_CONFIG_HOME="$PWD/.repro-signature/home/config" \ XDG_CACHE_HOME="$PWD/.repro-signature/home/cache" \ XDG_DATA_HOME="$PWD/.repro-signature/home/data" \ node scripts/rea.mjs inspect-signature .repro-signature/hardened-no-entitlement --format json > .repro-signature/hardened-no-entitlement.json ``` 3. Create an entitlement-bearing control and an unsigned control, then inspect both. ```sh cp .repro-signature/hardened-no-entitlement .repro-signature/hardened-with-entitlement cat > .repro-signature/entitlements.plist <<'EOF' <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"><dict><key>com.apple.security.get-task-allow</key><true/></dict></plist> EOF codesign --force --sign - --options runtime --identifier local.repro.allowed --entitlements .repro-signature/entitlements.plist .repro-signature/hardened-with-entitlement cp .repro-signature/hardened-no-entitlement .repro-signature/unsigned codesign --remove-signature .repro-signature/unsigned for target in hardened-with-entitlement unsigned; do env HOME="$PWD/.repro-signature/home" \ XDG_CONFIG_HOME="$PWD/.repro-signature/home/config" \ XDG_CACHE_HOME="$PWD/.repro-signature/home/cache" \ XDG_DATA_HOME="$PWD/.repro-signature/home/data" \ node scripts/rea.mjs inspect-signature ".repro-signature/$target" --format json > ".repro-signature/$target.json" done ``` 4. Print the returned signing facts and the complete key sets. Compare them with `docs/native-investigation.md:482-485` and the remediation in `src/native/LldbCallTracer.ts:165-166`. ```sh node --input-type=module <<'EOF' import { readFileSync } from 'node:fs'; for (const target of ['hardened-no-entitlement', 'hardened-with-entitlement', 'unsigned']) { const evidence = JSON.parse(readFileSync(`.repro-signature/${target}.json`, 'utf8')); const result = evidence.normalized_result; console.log(JSON.stringify({target, provider: evidence.provider.id, signed: result.signed, hardened_runtime: result.hardened_runtime, entitlements: result.entitlements, keys: Object.keys(result)})); } EOF ``` ### Expected behavior `docs/native-investigation.md:482-485` states that `inspect_signature` reports the missing debugging entitlement on a hardened-runtime target as a debugger-attach facet. `src/native/LldbCallTracer.ts:165-166` also directs callers to that facet. Following this guidance should identify an actual returned value or accurately explain how to read the existing signing facts. Accurate guidance about `hardened_runtime` and nullable `entitlements` is sufficient to resolve this wording defect; adding a separate derived field is not the only acceptable repair. Signing prerequisites alone must not become a guarantee that Developer Tools permission or every other debugger requirement is satisfied. ### Impact and scope P3, supported. Two caller-facing instructions name a nonexistent result facet, while the reproduced signature inspections complete and preserve the underlying signing facts. Callers can inspect `hardened_runtime` and raw `entitlements` directly, handling `entitlements: null` as well as an entitlement object. No loss of signing results or debugger enforcement failure was demonstrated. The verifier exercised the actual CLI with local compiler and signing tools and no provider fakes. Debugger launch and the `debugger-attach-denied` error itself were not exercised. This report makes no claim that either is broken or that MCP runtime behavior was reproduced. ### REA version 6.4.0 (main at 58300885207133422af235e0f2b10658cf958b03) ### Runtime and platform Node.js v26.10.0; macOS 27.0.1, build 26A434; arm64. Apple's local compiler and codesign were used. Hopper, Ghidra and LLDB are not required for signature inspection. ### Target and artifact context Locally compiled Mach-O arm64 executable containing `int main(void) { return 0; }`, with three variants: ad hoc signed with hardened runtime and no entitlements, ad hoc signed with hardened runtime and `com.apple.security.get-task-allow: true`, and unsigned. Each inspection returns native-macos Evidence. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence ```text provider: native-macos hardened-no-entitlement: signed=true, hardened_runtime=true, entitlements=null hardened-with-entitlement: signed=true, hardened_runtime=true, entitlements={"com.apple.security.get-task-allow":true} unsigned: signed=false, hardened_runtime=null, entitlements=null All three normalized_result key sets: signed, identifier, team_identifier, format, cdhashes, hash_algorithms, authorities, designated_requirement, entitlements, timestamp, hardened_runtime, provenance, limitations No debugger-attach facet appears in any result. ``` ### Typed outcome or recovery expected Repeat the three inspections and follow the revised guide and denial remediation. Both instructions should accurately identify returned signing information, either through the existing hardened-runtime and entitlement facts with null handling or through a facet the operation actually returns. The entitlement-bearing control must remain distinguishable from the target without entitlements, and the unsigned control must retain its explicit unknown hardened-runtime state. The guidance must keep signing prerequisites separate from overall debugger access. ### Analysis or suspected cause Source-derived at baseline `58300885207133422af235e0f2b10658cf958b03`: `docs/native-investigation.md:482-485` and `src/native/LldbCallTracer.ts:165-166` name the absent facet. `src/domain/native/nativeInspection.ts:146-160` defines the thirteen returned fields, and `src/native/NativeMacOSProvider.ts:598-673` constructs the result from codesign output and raw entitlements. These source definitions agree with the independently reproduced CLI key sets. The narrower tool description at `src/contracts/native/nativeToolContracts.ts:106-109` promises raw signing identity, entitlements and hardened-runtime state rather than a separate facet. ### Additional context Related: #934 proposed a broader signing-posture feature and closed without merging, #964 repeats the facet wording in its LLDB feature description, #2156 tracks other documentation findings, and #2397 investigates actual LLDB runtime failures; this report concerns only the inaccurate guide/remediation reference demonstrated by successful signature-inspection results.
bsakaguchi 2026-10-15 18:31:17 +00:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@morluto commented on GitHub (Oct 14, 2026):

Delivered on main in fffb07419.

Guidance advertised nonexistent native inspection facets. It now names the current contract fields and their actual evidence scope.

Validation: Contract/documentation checks and native inspection contract coverage; no debugger execution is claimed. Full exact-revision qualification passed.

<!-- gh-comment-id:6177628308 --> @morluto commented on GitHub (Oct 14, 2026): Delivered on main in [fffb07419](https://github.com/morluto/rea/commit/fffb0741936067530d1ce9777461cd53e87398c2). Guidance advertised nonexistent native inspection facets. It now names the current contract fields and their actual evidence scope. Validation: Contract/documentation checks and native inspection contract coverage; no debugger execution is claimed. Full exact-revision [qualification](https://github.com/morluto/rea/actions/runs/38629313022) passed.
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#1125
No description provided.