[PR #1099] [MERGED] fix(native): bind signature observations to registered target versions #2647

Closed
opened 2026-10-17 21:08:36 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1099
Author: @morluto
Created: 10/8/2026
Status: ✅ Merged
Merged: 10/8/2026
Merged by: @morluto

Base: main ← Head: codex/signature-target-backport


📝 Commits (4)

  • 8438672 fix(native): bind signature observations to registered target versions
  • cf8191f Merge remote-tracking branch 'origin/main' into codex/signature-target-backport
  • 8945124 fix(native): preserve target drift and cancellation across signature captures
  • b248840 fix(native): inspect signatures from a verified byte snapshot

📊 Changes

7 files changed (+908 additions, -36 deletions)

View changed files

📝 src/native/NativeMacOSProvider.ts (+86 -29)
➕ src/native/SignatureTargetBinding.ts (+272 -0)
➕ tests/boundary/mcp/nativeSignatureTargetBindingMcp.test.ts (+62 -0)
📝 tests/boundary/providers/native/nativeInventory.golden.test.ts (+32 -4)
📝 tests/boundary/providers/native/nativeProvider.test.ts (+6 -2)
➕ tests/boundary/providers/native/nativeSignatureTargetBinding.test.ts (+434 -0)
📝 tests/fixtures/nativeCommands.ts (+16 -1)

📄 Description

After open_binary, replacing or modifying the selected file could make inspect_signature report codesign observations for bytes that no longer matched the registered target digest. Changes between codesign captures could also mix observations from different file versions. A temporary ancestor-directory swap could evade pathname checks while codesign inspected another executable.

Bind signature inspection to the registered SHA-256 and a filesystem identity/version before running commands, verify that version before and after every codesign capture, including failed commands and per-architecture captures, and verify it again before publishing results. Hash and copy the same opened descriptor bytes through a bounded 64 KiB buffer, then run every codesign capture against that private read-only snapshot. The capture helper supplies the bound path itself; callers supply only command options. Release the snapshot on successful, failed, cancelled, and exceptional exits, preserve the original inspection failure if cleanup also fails, and reject symlink or non-file replacements. Results explicitly limit coverage to the byte snapshot rather than filesystem-bound signing context or trust validation. Preserve host permission failures as access_denied and target changes as artifact_changed; reopening the changed target establishes the new version for subsequent inspection. Cancellation during file acquisition and final checks returns the tagged cancellation result. Signature test fixtures register real files and matching digests, including the universal-image golden tests that previously failed CI. The signature result schema is unchanged.

This backports the target-binding fix identified while reviewing closed #934. The proposed signing-posture feature remains outside this change.

Validation:

  • npm run check and npm run check:fast
  • npm run docs:check
  • npm run test:focused -- tests/boundary/providers/native/nativeSignatureTargetBinding.test.ts tests/boundary/providers/native/nativeProvider.test.ts tests/boundary/providers/native/nativeInventory.golden.test.ts tests/boundary/cli/nativeSignatureCli.test.ts tests/boundary/mcp/nativeSignatureTargetBindingMcp.test.ts — 65 tests passed, including replacement, removal, symlink, same-content rewrite, permission failures, cancellation, failed display/supplemental/slice captures, intermediate inode replacement, snapshot content across chunk boundaries, cleanup on every exit path, and MCP recovery. A real codesign test swaps and restores the original ancestor directory during every capture and verifies that the registered signature remains the result.
  • Real macOS arm64 codesign CLI and stdio MCP verification with an ad hoc signed executable: unchanged inspection succeeds, re-signing after selection returns artifact_changed, and reopening allows inspection of the new identifier.

Hopper/Ghidra verification was not performed; signature inspection uses the native macOS provider.


🔄 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/1099 **Author:** [@morluto](https://github.com/morluto) **Created:** 10/8/2026 **Status:** ✅ Merged **Merged:** 10/8/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `codex/signature-target-backport` --- ### 📝 Commits (4) - [`8438672`](https://github.com/morluto/rea/commit/843867226d9b155d1003c125ef067b13901c7f2a) fix(native): bind signature observations to registered target versions - [`cf8191f`](https://github.com/morluto/rea/commit/cf8191f28c5b6bff8848a1702e4aed8a0dd82801) Merge remote-tracking branch 'origin/main' into codex/signature-target-backport - [`8945124`](https://github.com/morluto/rea/commit/8945124bbc1ac9ca6a856337e56a87f14c70409d) fix(native): preserve target drift and cancellation across signature captures - [`b248840`](https://github.com/morluto/rea/commit/b248840cafb11d41bdbd1262d257bca93c5aa79a) fix(native): inspect signatures from a verified byte snapshot ### 📊 Changes **7 files changed** (+908 additions, -36 deletions) <details> <summary>View changed files</summary> 📝 `src/native/NativeMacOSProvider.ts` (+86 -29) ➕ `src/native/SignatureTargetBinding.ts` (+272 -0) ➕ `tests/boundary/mcp/nativeSignatureTargetBindingMcp.test.ts` (+62 -0) 📝 `tests/boundary/providers/native/nativeInventory.golden.test.ts` (+32 -4) 📝 `tests/boundary/providers/native/nativeProvider.test.ts` (+6 -2) ➕ `tests/boundary/providers/native/nativeSignatureTargetBinding.test.ts` (+434 -0) 📝 `tests/fixtures/nativeCommands.ts` (+16 -1) </details> ### 📄 Description After `open_binary`, replacing or modifying the selected file could make `inspect_signature` report codesign observations for bytes that no longer matched the registered target digest. Changes between codesign captures could also mix observations from different file versions. A temporary ancestor-directory swap could evade pathname checks while codesign inspected another executable. Bind signature inspection to the registered SHA-256 and a filesystem identity/version before running commands, verify that version before and after every codesign capture, including failed commands and per-architecture captures, and verify it again before publishing results. Hash and copy the same opened descriptor bytes through a bounded 64 KiB buffer, then run every codesign capture against that private read-only snapshot. The capture helper supplies the bound path itself; callers supply only command options. Release the snapshot on successful, failed, cancelled, and exceptional exits, preserve the original inspection failure if cleanup also fails, and reject symlink or non-file replacements. Results explicitly limit coverage to the byte snapshot rather than filesystem-bound signing context or trust validation. Preserve host permission failures as `access_denied` and target changes as `artifact_changed`; reopening the changed target establishes the new version for subsequent inspection. Cancellation during file acquisition and final checks returns the tagged cancellation result. Signature test fixtures register real files and matching digests, including the universal-image golden tests that previously failed CI. The signature result schema is unchanged. This backports the target-binding fix identified while reviewing closed #934. The proposed signing-posture feature remains outside this change. Validation: - `npm run check` and `npm run check:fast` - `npm run docs:check` - `npm run test:focused -- tests/boundary/providers/native/nativeSignatureTargetBinding.test.ts tests/boundary/providers/native/nativeProvider.test.ts tests/boundary/providers/native/nativeInventory.golden.test.ts tests/boundary/cli/nativeSignatureCli.test.ts tests/boundary/mcp/nativeSignatureTargetBindingMcp.test.ts` — 65 tests passed, including replacement, removal, symlink, same-content rewrite, permission failures, cancellation, failed display/supplemental/slice captures, intermediate inode replacement, snapshot content across chunk boundaries, cleanup on every exit path, and MCP recovery. A real codesign test swaps and restores the original ancestor directory during every capture and verifies that the registered signature remains the result. - Real macOS arm64 codesign CLI and stdio MCP verification with an ad hoc signed executable: unchanged inspection succeeds, re-signing after selection returns `artifact_changed`, and reopening allows inspection of the new identifier. Hopper/Ghidra verification was not performed; signature inspection uses the native macOS provider. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:08:36 +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#2647
No description provided.