Repository navigation
Description
Parent: #227
Release consumer: SceneTech/AppScene#130
Problem
The exact installed-SDK Code OSS Release at AppScene cac13616 / WebScene 54158141 reaches recursive macOS bundle auditing, then fails before signing because three third-party Node native modules carry producer-machine absolute LC_ID_DYLIB values:
server/node_modules/@github/copilot-darwin-arm64/prebuilds/darwin-arm64/runtime.nodeserver/extensions/copilot/node_modules/@github/copilot/sdk/prebuilds/darwin-arm64/cli-native.nodeserver/extensions/copilot/node_modules/@github/copilot/sdk/prebuilds/darwin-arm64/runtime.node
The identifiers point below /Users/runner/work/copilot-agent-runtime/.... These are dylib identities, not unresolved runtime dependencies. WebScene's package_macos.py already relocates SDK framework identities and recursively audits every bundled Mach-O, but it does not normalize identities of application-supplied .node/.dylib payloads before that audit. The fail-closed audit correctly rejects the absolute producer path.
Proposed fix
Before recursive audit and signing, enumerate bounded regular Mach-O files inside the bundle and normalize every non-system absolute LC_ID_DYLIB to a loader-safe identity such as @rpath/<basename>. Do not weaken audit_macos_bundle.py: the post-normalization audit must continue rejecting any remaining absolute identity, dependency or rpath. Preserve slice normalization, dependency-closure checks, nested signing order and immutable installed-SDK behavior.
Normalization must be deterministic, fail closed on malformed load commands, avoid symlink traversal and record enough evidence to prove exactly which identities changed. Application-specific source patching is not acceptable because the generic SDK packager owns relocatable macOS bundle output.
Acceptance
- A fixture
.nodewith an absolute producerLC_ID_DYLIBis normalized and passes the existing recursive audit/signing flow. - System identities and already relative identities remain byte-for-byte unchanged.
- Absolute dependencies and rpaths remain rejected; the fix cannot turn them into silent basename matches.
- The exact three Code OSS Copilot native modules lose every
/Users/runner/work/...identifier and remain loadable by Node 24. - Recursive architecture, deployment-target, dependency-closure, signing and no-browser evidence still pass.
- The installed SDK inventory is unchanged before/after packaging.
- Repeated qualification stays within the existing 25,000-entry bound and adds a measured time/RSS budget for the scan.
Exact reproduction
Run the Release through the installed AppScene CLI with the 2,868-file SDK archive SHA-256 6f2495278484a811323d9565dea0cc0abb79110540678d6ca02877980fc4ed7a. Packaging stops in audit_macos_bundle.validate_install_name() on libcli_native.dylib after the unchanged server payload is staged.
Activity
wieslawsoltes commentedon Sep 18, 2026
Implementation is open in PR #412 at
4afbfa51. Local gates pass: portable/adversarial 24/24; installed macOS fixture thins, relocates, signs and dynamically loads both extensions, then produces ten deterministic four-Mach-O audits in 2.417 s. The exact 21,007-entry Code OSS bundle now passes recursive packaging: three producer identities are recorded and rewritten, all three modules load in Node 24.18.1, and deep strict signing verifies. Direct source/schema/installed-consumer CI is running; unrelated matrix jobs were canceled.