Skip to content

Normalize application Mach-O identities before macOS bundle audit #410

Closed

Description

@wieslawsoltes

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.node
  • server/extensions/copilot/node_modules/@github/copilot/sdk/prebuilds/darwin-arm64/cli-native.node
  • server/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 .node with an absolute producer LC_ID_DYLIB is 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

  1. added
    bugSomething isn't working
    vscode-oss/plannedPlanned for the AppScene/WebScene VS Code OSS integration
    on Sep 18, 2026
  2. wieslawsoltes commented on Sep 18, 2026

    @wieslawsoltes
    CollaboratorAuthor

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingvscode-oss/plannedPlanned for the AppScene/WebScene VS Code OSS integration

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions