Preserve entitlements when re-signing managed runtime binaries

The sign script was re-signing Mach-O executables with --force and
hardened runtime but without --entitlements, stripping entitlements
like allow-jit that Node.js needs for V8. This caused SIGTRAP on
any Mac where the binary went through Gatekeeper validation.

Extract existing entitlements before re-signing and pass them back
via --entitlements so they are preserved.
This commit is contained in:
Mohamed Boudra
2026-03-11 11:36:21 +07:00
parent e2068e3d72
commit c37684b246

View File

@@ -74,6 +74,17 @@ function needsHardenedRuntime(fileKind) {
return fileKind.includes("executable"); return fileKind.includes("executable");
} }
function extractEntitlements(file) {
const result = spawnSync("codesign", ["-d", "--entitlements", "-", "--xml", file], {
stdio: "pipe",
encoding: "utf8",
});
if (result.status !== 0 || !result.stdout || result.stdout.trim().length === 0) {
return null;
}
return result.stdout;
}
async function main() { async function main() {
const pointer = JSON.parse( const pointer = JSON.parse(
await fs.readFile(path.join(resourcesRoot, "current-runtime.json"), "utf8") await fs.readFile(path.join(resourcesRoot, "current-runtime.json"), "utf8")
@@ -99,6 +110,15 @@ async function main() {
signTargets.sort((left, right) => left.file.localeCompare(right.file)); signTargets.sort((left, right) => left.file.localeCompare(right.file));
for (const target of signTargets) { for (const target of signTargets) {
let entitlementsFile = null;
if (target.needsRuntime) {
const entitlements = extractEntitlements(target.file);
if (entitlements) {
entitlementsFile = `${target.file}.entitlements.plist`;
await fs.writeFile(entitlementsFile, entitlements, "utf8");
}
}
const args = [ const args = [
"--force", "--force",
"--sign", "--sign",
@@ -107,10 +127,17 @@ async function main() {
]; ];
if (target.needsRuntime) { if (target.needsRuntime) {
args.push("--options", "runtime"); args.push("--options", "runtime");
if (entitlementsFile) {
args.push("--entitlements", entitlementsFile);
}
} }
args.push(target.file); args.push(target.file);
console.log(`[managed-runtime-sign] ${path.relative(repoRoot, target.file)}`); console.log(`[managed-runtime-sign] ${path.relative(repoRoot, target.file)}`);
run("codesign", args); run("codesign", args);
if (entitlementsFile) {
await fs.unlink(entitlementsFile);
}
} }
} }