seabox 0.1.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/unsign.cjs CHANGED
@@ -1,169 +1,197 @@
1
- /**
2
- * unsign.js
3
- * Remove code signatures from executables before injection.
4
- * This prevents signature corruption during postject injection.
5
- */
6
-
7
- const { execFile } = require('child_process');
8
- const { promisify } = require('util');
9
-
10
- const execFileAsync = promisify(execFile);
11
-
12
- // Simple verbose logging flag (set by inject.mjs)
13
- let verboseMode = false;
14
- function setVerbose(enabled) {
15
- verboseMode = enabled;
16
- }
17
-
18
- function logVerbose(message, indent = 2) {
19
- if (verboseMode) {
20
- console.log(' '.repeat(indent) + message);
21
- }
22
- }
23
-
24
- /**
25
- * Check if a signing tool is available on the system.
26
- * @param {string} platform - Target platform (win32, linux, darwin)
27
- * @returns {Promise<{available: boolean, tool: string|null}>}
28
- */
29
- async function checkSignToolAvailability(platform) {
30
- const tools = {
31
- win32: 'signtool.exe',
32
- darwin: 'codesign',
33
- };
34
-
35
- const tool = tools[platform];
36
- if (!tool) {
37
- return { available: false, tool: null };
38
- }
39
-
40
- try {
41
- // Try to execute the tool with a version/help flag to check availability
42
- if (platform === 'win32') {
43
- await execFileAsync('where', ['signtool.exe']);
44
- } else if (platform === 'darwin') {
45
- await execFileAsync('which', ['codesign']);
46
- }
47
- return { available: true, tool };
48
- } catch (error) {
49
- return { available: false, tool };
50
- }
51
- }
52
-
53
- /**
54
- * Remove signature from a Windows executable using signtool.
55
- * @param {string} exePath - Path to the executable
56
- * @returns {Promise<{success: boolean, message: string}>}
57
- */
58
- async function removeWindowsSignature(exePath) {
59
- try {
60
- const { stdout, stderr } = await execFileAsync('signtool.exe', ['remove', '/s', exePath]);
61
-
62
- const output = (stdout + stderr).toLowerCase();
63
-
64
- // Check if successfully removed
65
- if (output.includes('successfully')) {
66
- return { success: true, message: 'Signature removed successfully' };
67
- }
68
-
69
- // Check if there was no signature
70
- if (output.includes('no signature') || output.includes('not signed')) {
71
- return { success: true, message: 'Binary was not signed (no signature to remove)' };
72
- }
73
-
74
- return { success: true, message: stdout || 'Signature removal completed' };
75
- } catch (error) {
76
- const errorMsg = error.message || error.stderr || '';
77
-
78
- // Not an error if there was no signature to begin with
79
- if (errorMsg.includes('No signature') || errorMsg.includes('not signed')) {
80
- return { success: true, message: 'Binary was not signed (no signature to remove)' };
81
- }
82
-
83
- return { success: false, message: `Failed to remove signature: ${errorMsg}` };
84
- }
85
- }
86
-
87
- /**
88
- * Remove signature from a macOS executable using codesign.
89
- * @param {string} exePath - Path to the executable
90
- * @returns {Promise<{success: boolean, message: string}>}
91
- */
92
- async function removeMacSignature(exePath) {
93
- try {
94
- // On macOS, use --remove-signature flag
95
- const { stdout, stderr } = await execFileAsync('codesign', ['--remove-signature', exePath]);
96
-
97
- return { success: true, message: 'Signature removed successfully' };
98
- } catch (error) {
99
- const errorMsg = error.message || error.stderr || '';
100
-
101
- // Not an error if there was no signature
102
- if (errorMsg.includes('not signed') || errorMsg.includes('no signature')) {
103
- return { success: true, message: 'Binary was not signed (no signature to remove)' };
104
- }
105
-
106
- return { success: false, message: `Failed to remove signature: ${errorMsg}` };
107
- }
108
- }
109
-
110
-
111
- /**
112
- * Remove code signature from an executable before injection.
113
- * This is critical to prevent signature corruption during postject injection.
114
- * @param {string} exePath - Path to the executable
115
- * @param {string} platform - Target platform (win32, linux, darwin)
116
- * @returns {Promise<void>}
117
- */
118
- async function removeSignature(exePath, platform) {
119
- // Linux binaries are typically not signed, so skip signature removal
120
- if (platform === 'linux') {
121
- logVerbose('Skipping signature removal (Linux binaries are typically unsigned)');
122
- return;
123
- }
124
-
125
- const { available, tool } = await checkSignToolAvailability(platform);
126
-
127
- if (!available) {
128
- logVerbose(`[!] Warning: Signature removal tool not found for ${platform}`);
129
- logVerbose(`Tool needed: ${tool || 'unknown'}`, 2);
130
- logVerbose(`The binary may have an existing signature that will be corrupted during injection.`, 2);
131
-
132
- if (platform === 'win32') {
133
- logVerbose(`Install Windows SDK to get signtool.exe`, 2);
134
- logVerbose(`Download from: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/`, 2);
135
- } else if (platform === 'darwin') {
136
- logVerbose(`Install Xcode Command Line Tools to get codesign`, 2);
137
- logVerbose(`Run: xcode-select --install`, 2);
138
- }
139
-
140
- return;
141
- }
142
-
143
- logVerbose(`Found ${tool}, attempting to remove signature...`);
144
-
145
- let result;
146
- if (platform === 'win32') {
147
- result = await removeWindowsSignature(exePath);
148
- } else if (platform === 'darwin') {
149
- result = await removeMacSignature(exePath);
150
- } else {
151
- logVerbose(`[!] Warning: Unsupported platform for signature removal: ${platform}`);
152
- return;
153
- }
154
-
155
- if (result.success) {
156
- logVerbose(`[] ${result.message}`);
157
- } else {
158
- logVerbose(`[!] Warning: ${result.message}`);
159
- logVerbose(`Continuing anyway, but the executable may have signature issues.`, 2);
160
- }
161
- }
162
-
163
- module.exports = {
164
- removeSignature,
165
- checkSignToolAvailability,
166
- removeWindowsSignature,
167
- removeMacSignature,
168
- setVerbose,
169
- };
1
+ /**
2
+ * unsign.js
3
+ * Remove code signatures from executables before injection.
4
+ * This prevents signature corruption during postject injection.
5
+ */
6
+
7
+ const { execFile } = require('child_process');
8
+ const { promisify } = require('util');
9
+
10
+ const execFileAsync = promisify(execFile);
11
+
12
+ // Simple verbose logging flag (set by inject.mjs)
13
+ let verboseMode = false;
14
+ function setVerbose(enabled) {
15
+ verboseMode = enabled;
16
+ }
17
+
18
+ function logVerbose(message, indent = 2) {
19
+ if (verboseMode) {
20
+ console.log(' '.repeat(indent) + message);
21
+ }
22
+ }
23
+
24
+ function delay(ms) {
25
+ return new Promise(resolve => setTimeout(resolve, ms));
26
+ }
27
+
28
+ /**
29
+ * Check if a signing tool is available on the system.
30
+ * @param {string} platform - Target platform (win32, linux, darwin)
31
+ * @returns {Promise<{available: boolean, tool: string|null}>}
32
+ */
33
+ async function checkSignToolAvailability(platform) {
34
+ const tools = {
35
+ win32: 'signtool.exe',
36
+ darwin: 'codesign',
37
+ };
38
+
39
+ const tool = tools[platform];
40
+ if (!tool) {
41
+ return { available: false, tool: null };
42
+ }
43
+
44
+ try {
45
+ // Try to execute the tool with a version/help flag to check availability
46
+ if (platform === 'win32') {
47
+ await execFileAsync('where', ['signtool.exe']);
48
+ } else if (platform === 'darwin') {
49
+ await execFileAsync('which', ['codesign']);
50
+ }
51
+ return { available: true, tool };
52
+ } catch (error) {
53
+ return { available: false, tool };
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Remove signature from a Windows executable using signtool.
59
+ * @param {string} exePath - Path to the executable
60
+ * @returns {Promise<{success: boolean, message: string}>}
61
+ */
62
+ async function removeWindowsSignature(exePath) {
63
+ let lastError = null;
64
+
65
+ for (let attempt = 1; attempt <= 3; attempt++) {
66
+ try {
67
+ const { stdout, stderr } = await execFileAsync('signtool.exe', ['remove', '/s', exePath]);
68
+
69
+ const output = (stdout + stderr).toLowerCase();
70
+
71
+ // Check if successfully removed
72
+ if (output.includes('successfully')) {
73
+ return { success: true, message: 'Signature removed successfully' };
74
+ }
75
+
76
+ // Check if there was no signature
77
+ if (output.includes('no signature') || output.includes('not signed')) {
78
+ return { success: true, message: 'Binary was not signed (no signature to remove)' };
79
+ }
80
+
81
+ return { success: true, message: stdout || 'Signature removal completed' };
82
+ } catch (error) {
83
+ const errorMsg = error.message || error.stderr || '';
84
+
85
+ // Not an error if there was no signature to begin with
86
+ if (errorMsg.includes('No signature') || errorMsg.includes('not signed')) {
87
+ return { success: true, message: 'Binary was not signed (no signature to remove)' };
88
+ }
89
+
90
+ lastError = errorMsg;
91
+
92
+ // If not the last attempt, wait before retrying
93
+ if (attempt < 3) {
94
+ await delay(500);
95
+ continue;
96
+ }
97
+ }
98
+ }
99
+
100
+ return { success: false, message: `Failed to remove signature: ${lastError}` };
101
+ }
102
+
103
+ /**
104
+ * Remove signature from a macOS executable using codesign.
105
+ * @param {string} exePath - Path to the executable
106
+ * @returns {Promise<{success: boolean, message: string}>}
107
+ */
108
+ async function removeMacSignature(exePath) {
109
+ let lastError = null;
110
+
111
+ for (let attempt = 1; attempt <= 3; attempt++) {
112
+ try {
113
+ // On macOS, use --remove-signature flag
114
+ const { stdout, stderr } = await execFileAsync('codesign', ['--remove-signature', exePath]);
115
+
116
+ return { success: true, message: 'Signature removed successfully' };
117
+ } catch (error) {
118
+ const errorMsg = error.message || error.stderr || '';
119
+
120
+ // Not an error if there was no signature
121
+ if (errorMsg.includes('not signed') || errorMsg.includes('no signature')) {
122
+ return { success: true, message: 'Binary was not signed (no signature to remove)' };
123
+ }
124
+
125
+ lastError = errorMsg;
126
+
127
+ // If not the last attempt, wait before retrying
128
+ if (attempt < 3) {
129
+ await delay(500);
130
+ continue;
131
+ }
132
+ }
133
+ }
134
+
135
+ return { success: false, message: `Failed to remove signature: ${lastError}` };
136
+ }
137
+
138
+
139
+ /**
140
+ * Remove code signature from an executable before injection.
141
+ * This is critical to prevent signature corruption during postject injection.
142
+ * @param {string} exePath - Path to the executable
143
+ * @param {string} platform - Target platform (win32, linux, darwin)
144
+ * @returns {Promise<void>}
145
+ */
146
+ async function removeSignature(exePath, platform) {
147
+ // Linux binaries are typically not signed, so skip signature removal
148
+ if (platform === 'linux') {
149
+ logVerbose('Skipping signature removal (Linux binaries are typically unsigned)');
150
+ return;
151
+ }
152
+
153
+ const { available, tool } = await checkSignToolAvailability(platform);
154
+
155
+ if (!available) {
156
+ logVerbose(`[!] Warning: Signature removal tool not found for ${platform}`);
157
+ logVerbose(`Tool needed: ${tool || 'unknown'}`, 2);
158
+ logVerbose(`The binary may have an existing signature that will be corrupted during injection.`, 2);
159
+
160
+ if (platform === 'win32') {
161
+ logVerbose(`Install Windows SDK to get signtool.exe`, 2);
162
+ logVerbose(`Download from: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/`, 2);
163
+ } else if (platform === 'darwin') {
164
+ logVerbose(`Install Xcode Command Line Tools to get codesign`, 2);
165
+ logVerbose(`Run: xcode-select --install`, 2);
166
+ }
167
+
168
+ return;
169
+ }
170
+
171
+ logVerbose(`Found ${tool}, attempting to remove signature...`);
172
+
173
+ let result;
174
+ if (platform === 'win32') {
175
+ result = await removeWindowsSignature(exePath);
176
+ } else if (platform === 'darwin') {
177
+ result = await removeMacSignature(exePath);
178
+ } else {
179
+ logVerbose(`[!] Warning: Unsupported platform for signature removal: ${platform}`);
180
+ return;
181
+ }
182
+
183
+ if (result.success) {
184
+ logVerbose(`[✓] ${result.message}`);
185
+ } else {
186
+ logVerbose(`[!] Warning: ${result.message}`);
187
+ logVerbose(`Continuing anyway, but the executable may have signature issues.`, 2);
188
+ }
189
+ }
190
+
191
+ module.exports = {
192
+ removeSignature,
193
+ checkSignToolAvailability,
194
+ removeWindowsSignature,
195
+ removeMacSignature,
196
+ setVerbose,
197
+ };
package/package.json CHANGED
@@ -1,61 +1,61 @@
1
- {
2
- "name": "seabox",
3
- "version": "0.1.2",
4
- "description": "Node.js Single Executable Application (SEA) builder tool with native and library extraction",
5
- "main": "lib/index.mjs",
6
- "type": "module",
7
- "bin": {
8
- "seabox": "bin/seabox.mjs"
9
- },
10
- "scripts": {
11
- "clean": "rimraf dist",
12
- "prepublishOnly": "",
13
- "test": "mocha"
14
- },
15
- "keywords": [
16
- "sea",
17
- "build",
18
- "builder",
19
- "single-executable",
20
- "SEA",
21
- "native",
22
- "module",
23
- "pkg",
24
- "dll",
25
- "packaging",
26
- "node",
27
- "postject"
28
- ],
29
- "author": "Meirion Hughes",
30
- "license": "MIT",
31
- "repository": {
32
- "type": "git",
33
- "url": "https://github.com/MeirionHughes/seabox"
34
- },
35
- "homepage": "https://github.com/MeirionHughes/seabox",
36
- "dependencies": {
37
- "adm-zip": "^0.5.16",
38
- "glob": "^10.0.0",
39
- "postject": "^1.0.0-alpha.6",
40
- "rolldown": "^1.0.0-beta.50",
41
- "tar": "^6.2.1"
42
- },
43
- "peerDependencies": {
44
- "rcedit": "^4.0.1"
45
- },
46
- "peerDependenciesMeta": {
47
- "rcedit": {
48
- "optional": true
49
- }
50
- },
51
- "devDependencies": {
52
- "chai": "^6.2.1",
53
- "javascript-obfuscator": "^4.1.1",
54
- "mocha": "^11.7.5",
55
- "node-api-headers": "^1.2.0",
56
- "rimraf": "^6.0.1"
57
- },
58
- "engines": {
59
- "node": ">=18.0.0"
60
- }
61
- }
1
+ {
2
+ "name": "seabox",
3
+ "version": "0.3.0",
4
+ "description": "Node.js Single Executable Application (SEA) builder tool with native and library extraction",
5
+ "main": "lib/index.mjs",
6
+ "type": "module",
7
+ "bin": {
8
+ "seabox": "bin/seabox.mjs"
9
+ },
10
+ "scripts": {
11
+ "clean": "rimraf dist",
12
+ "prepublishOnly": "",
13
+ "test": "mocha"
14
+ },
15
+ "keywords": [
16
+ "sea",
17
+ "build",
18
+ "builder",
19
+ "single-executable",
20
+ "SEA",
21
+ "native",
22
+ "module",
23
+ "pkg",
24
+ "dll",
25
+ "packaging",
26
+ "node",
27
+ "postject"
28
+ ],
29
+ "author": "Meirion Hughes",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/MeirionHughes/seabox"
34
+ },
35
+ "homepage": "https://github.com/MeirionHughes/seabox",
36
+ "dependencies": {
37
+ "adm-zip": "^0.5.16",
38
+ "glob": "^10.0.0",
39
+ "postject": "^1.0.0-alpha.6",
40
+ "rolldown": "^1.0.0-beta.50",
41
+ "tar": "^6.2.1"
42
+ },
43
+ "peerDependencies": {
44
+ "rcedit": "^4.0.1"
45
+ },
46
+ "peerDependenciesMeta": {
47
+ "rcedit": {
48
+ "optional": true
49
+ }
50
+ },
51
+ "devDependencies": {
52
+ "chai": "^6.2.1",
53
+ "javascript-obfuscator": "^4.1.1",
54
+ "mocha": "^11.7.5",
55
+ "node-api-headers": "^1.2.0",
56
+ "rimraf": "^6.0.1"
57
+ },
58
+ "engines": {
59
+ "node": ">=18.0.0"
60
+ }
61
+ }