Skip to content

pack_dashmate.sh tarball mode drops the cpu-features skip, so the macOS package ships an unsigned native addon #5345

Closed

Description

@romchornyi

Expected Behavior

The Dashmate macOS package contains no native code except the bundled node binary, so Apple can notarize it. cpu-features stays replaced by @favware/skip-dependency, as set up in #985.

Current Behavior

Packages built by the release workflow since #5235 contain a compiled cpu-features:

  • node_modules/cpu-features/build/Release/cpufeatures.node — ad-hoc (linker) signature only
  • 15 object files under node_modules/cpu-features/build/Release/obj.target/ — not signed

Seen in both dashmate-v5.0.0-beta.3-bb78fa2220-arm64.pkg and -x64.pkg, taken from the dashmate-macos-<sha> artifact of the v5.0.0-beta.3 release run. In the x64 package these files are arm64, the runner's architecture.

For comparison, the released dashmate-v4.2.0-beta.4-6c95cd8b16-arm64.pkg has a single Mach-O file, bin/node, signed by the Node.js Foundation with the hardened runtime.

Apple has not seen such a package yet, because the notarize step currently fails at login (#5344). #985 removed this dependency because it "prevents MacOs installer notarization", so a rejection is expected.

Possible Solution

The tarball mode added to scripts/pack_dashmate.sh in #5235 replaces resolutions with a new object before yarn install:

if [ -n "${DASHMATE_NPM_TARBALLS_DIR:-}" ]; then
DASHMATE_NPM_TARBALLS_DIR="$(realpath "$DASHMATE_NPM_TARBALLS_DIR")" node -e '
const fs = require("fs");
const path = require("path");
const { execFileSync } = require("child_process");
const dir = process.env.DASHMATE_NPM_TARBALLS_DIR;
const p = JSON.parse(fs.readFileSync("package.json", "utf8"));
const tarballs = fs.readdirSync(dir).filter((file) => file.endsWith(".tgz"));
if (tarballs.length === 0) throw new Error(`No npm tarballs in ${dir}`);
p.resolutions = {};
for (const file of tarballs) {
const tarball = path.join(dir, file);
const { name } = JSON.parse(execFileSync("tar", ["-xOzf", tarball, "package/package.json"], { encoding: "utf8" }));
if (name !== p.name) p.resolutions[name] = `file:${tarball}`;
}
fs.writeFileSync("package.json", JSON.stringify(p, null, 2) + "\n");
'
fi
yarn install --no-immutable

That drops the entry that skips cpu-features:

"resolutions": {
"cpu-features": "https://registry.yarnpkg.com/@favware/skip-dependency/-/skip-dependency-1.2.1.tgz"
},

ssh2 lists cpu-features as an optional dependency, so without the entry yarn installs and compiles it. The release workflow always sets DASHMATE_NPM_TARBALLS_DIR, so every release package is built this way:

DASHMATE_NPM_TARBALLS_DIR: ${{ github.workspace }}/npm-packages

Fix: keep the existing entries and add the tarball ones to them, for example p.resolutions = p.resolutions || {};.

Optional guard: fail the macOS build when the package contains a Mach-O file other than bin/node.

Steps to Reproduce (for bugs)

  1. Download the dashmate-macos-bb78fa2220ae0d58f5a9b5c0f6b0027a292cc3d0 artifact from the release run above (kept until 2026-10-15), or build on macOS with DASHMATE_UNSIGNED=true DASHMATE_NPM_TARBALLS_DIR=<npm tarballs> scripts/pack_dashmate.sh macos.
  2. pkgutil --expand-full dashmate-v5.0.0-beta.3-bb78fa2220-arm64.pkg expanded
  3. find expanded -type f -exec file {} + | grep -c Mach-O prints 17. The v4.2.0-beta.4 package gives 1.
  4. codesign -dvv expanded/Payload/node_modules/cpu-features/build/Release/cpufeatures.node prints Signature=adhoc.

Context

Once #5344 restores the notary login, the macOS release job is expected to fail at notarization, and the release will again have no macOS installer. #5344 makes a rejection fail the job instead of uploading a rejected package.

Related: #5344 (notary login), #5235 (introduced the tarball mode), #985 (removed cpu-features).

Your Environment

  • Version used: v5.0.0-beta.3 (bb78fa2220), v5.0-dev
  • Environment name and version: Release Platform workflow, macos-14 arm64 runner
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 workingdashmateDashmate related

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions