Skip to content

Commit 655babf

Browse files
committed
Fix macOS ARM64 stub binary malformation with ldid support
Update build-stub.mjs to use ldid for signing ARM64 macOS binaries, which fixes the yao-pkg issue where code signature overlaps with string table causing malformed binaries. Changes: - Remove hardcoded node path from pkg.json - Add ldid detection and signing for ARM64 macOS - Skip redundant codesign that corrupts binaries - Add --no-bytecode and --compress flags to pkg - Provide clear instructions when ldid is not installed
1 parent 09312b9 commit 655babf

File tree

2 files changed

+99
-12
lines changed

2 files changed

+99
-12
lines changed

.config/pkg.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
"socket-pnpm": "dist/pnpm-cli.js",
88
"socket-yarn": "dist/yarn-cli.js"
99
},
10-
"node": "/Users/jdalton/projects/socket-cli/build/socket-node/node-yao-pkg/out/Release/node",
1110
"bytecode": false,
1211
"targets": [
1312
"node24-macos-arm64",

scripts/build/build-stub.mjs

Lines changed: 99 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,11 @@ export async function buildStub(options = {}) {
101101
'exec', 'pkg',
102102
PKG_CONFIG,
103103
'--targets', target,
104-
'--output', outputPath
104+
'--output', outputPath,
105+
// Avoid bytecode compilation which can cause malformed binaries
106+
'--no-bytecode',
107+
// Use compression to reduce size
108+
'--compress', 'GZip'
105109
]
106110

107111
const env = { ...process.env }
@@ -207,15 +211,29 @@ export async function buildStub(options = {}) {
207211
return 1
208212
}
209213

210-
// Step 5: Sign the binary on macOS
211-
if (platform === 'darwin' && existsSync(outputPath)) {
212-
console.log('🔏 Signing macOS binary...')
213-
const signExitCode = await signMacOSBinary(outputPath, quiet)
214-
if (signExitCode !== 0) {
215-
console.error('⚠️ Warning: Failed to sign macOS binary')
216-
console.error(' The binary may not run properly without signing')
214+
// Step 5: Sign with ldid on ARM64 macOS (fixes yao-pkg malformed binary issue)
215+
if (platform === 'darwin' && arch === 'arm64' && existsSync(outputPath)) {
216+
console.log('🔏 Signing macOS ARM64 binary...')
217+
const signResult = await signMacOSBinaryWithLdid(outputPath, quiet)
218+
if (signResult === 'ldid-not-found') {
219+
console.error('⚠️ Warning: ldid not found - binary may be malformed')
220+
console.error(' Install ldid to fix: brew install ldid')
221+
console.error(' Then manually sign: ldid -S ./binaries/stub/socket-macos-arm64')
222+
} else if (signResult !== 0) {
223+
console.error('⚠️ Warning: Failed to sign with ldid')
217224
} else {
218-
console.log('✅ Binary signed successfully\n')
225+
console.log('✅ Binary signed with ldid successfully\n')
226+
}
227+
}
228+
// For x64 or if ldid wasn't used, verify the signature
229+
else if (platform === 'darwin' && existsSync(outputPath)) {
230+
console.log('🔏 Verifying macOS binary signature...')
231+
const isSignedProperly = await verifyMacOSBinarySignature(outputPath, quiet)
232+
if (!isSignedProperly) {
233+
console.error('⚠️ Warning: Binary may not be properly signed')
234+
console.error(' The binary may not run properly')
235+
} else {
236+
console.log('✅ Binary signature verified\n')
219237
}
220238
}
221239

@@ -240,9 +258,79 @@ export async function buildStub(options = {}) {
240258
}
241259

242260
/**
243-
* Sign macOS binary using codesign
261+
* Sign macOS ARM64 binary with ldid (fixes yao-pkg malformed binary issue)
262+
*/
263+
async function signMacOSBinaryWithLdid(binaryPath, quiet = false) {
264+
// First check if ldid is available
265+
const ldidAvailable = await new Promise((resolve) => {
266+
const child = spawn('which', ['ldid'], {
267+
stdio: 'pipe'
268+
})
269+
child.on('exit', (code) => resolve(code === 0))
270+
child.on('error', () => resolve(false))
271+
})
272+
273+
if (!ldidAvailable) {
274+
return 'ldid-not-found'
275+
}
276+
277+
// Remove existing signature first (if any)
278+
await new Promise((resolve) => {
279+
const child = spawn('codesign', ['--remove-signature', binaryPath], {
280+
stdio: 'pipe'
281+
})
282+
child.on('exit', () => resolve())
283+
child.on('error', () => resolve())
284+
})
285+
286+
// Sign with ldid
287+
return new Promise((resolve) => {
288+
const child = spawn('ldid', ['-S', binaryPath], {
289+
stdio: quiet ? 'pipe' : 'inherit'
290+
})
291+
292+
child.on('exit', (code) => {
293+
resolve(code || 0)
294+
})
295+
child.on('error', (error) => {
296+
if (!quiet) {
297+
console.error(' ldid error:', error.message)
298+
}
299+
resolve(1)
300+
})
301+
})
302+
}
303+
304+
/**
305+
* Verify macOS binary signature
306+
*/
307+
async function verifyMacOSBinarySignature(binaryPath, quiet = false) {
308+
return new Promise((resolve) => {
309+
const child = spawn('codesign', ['-dv', binaryPath], {
310+
stdio: 'pipe'
311+
})
312+
313+
let stderr = ''
314+
child.stderr.on('data', (data) => {
315+
stderr += data.toString()
316+
})
317+
318+
child.on('exit', (code) => {
319+
// Exit code 0 means it's properly signed
320+
if (!quiet && code !== 0) {
321+
console.error(' Signature verification failed:', stderr.trim())
322+
}
323+
resolve(code === 0)
324+
})
325+
child.on('error', () => resolve(false))
326+
})
327+
}
328+
329+
/**
330+
* Sign macOS binary using codesign (DEPRECATED - pkg handles this)
331+
* @deprecated pkg should handle signing during build
244332
*/
245-
async function signMacOSBinary(binaryPath, quiet = false) {
333+
async function _signMacOSBinary(binaryPath, quiet = false) {
246334
// First check if already signed
247335
const checkSigned = await new Promise((resolve) => {
248336
const child = spawn('codesign', ['-dv', binaryPath], {

0 commit comments

Comments
 (0)