sandboxbox 1.0.9 → 1.2.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/scripts/build.js +63 -158
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sandboxbox",
3
- "version": "1.0.9",
3
+ "version": "1.2.0",
4
4
  "description": "Zero-privilege container runner with Playwright support",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/scripts/build.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  /**
4
4
  * SQLite-style build script for SandboxBox
5
- * Downloads and compiles bubblewrap binary during npm install
5
+ * Downloads bubblewrap binary during npm install, with fallback to building from source
6
6
  */
7
7
 
8
8
  import fs from 'fs';
@@ -46,21 +46,29 @@ async function downloadAndBuild() {
46
46
  }
47
47
  }
48
48
 
49
- // Build from source like SQLite does - the ONLY method
49
+ // SQLite-style approach: try binary downloads first, then build from source
50
+ if (await downloadPreBuiltBinary(binaryPath)) {
51
+ return; // Binary download succeeded
52
+ }
53
+
50
54
  if (await buildFromSource(binaryPath)) {
51
- return; // Build succeeded
52
- } else {
53
- // Build failed - exit with error to make the problem visible
54
- console.error('❌ Bubblewrap build failed!');
55
- console.error('');
56
- console.error('💡 Install build tools:');
57
- console.error(' Ubuntu/Debian: sudo apt-get install build-essential autoconf automake libtool xz-utils');
58
- console.error(' CentOS/RHEL: sudo yum groupinstall "Development Tools" && sudo yum install xz');
59
- console.error('');
60
- console.error('🚫 SandboxBox cannot function without bubblewrap.');
61
- console.error(' Please install build tools and try again.');
62
- process.exit(1);
55
+ return; // Build from source succeeded
63
56
  }
57
+
58
+ // Everything failed - show clear error
59
+ console.error('❌ All bubblewrap installation methods failed!');
60
+ console.error('');
61
+ console.error('💡 Option 1 - Install system bubblewrap (recommended):');
62
+ console.error(' sudo apt-get install bubblewrap # Ubuntu/Debian');
63
+ console.error(' sudo apk add bubblewrap # Alpine');
64
+ console.error(' sudo yum install bubblewrap # CentOS/RHEL');
65
+ console.error('');
66
+ console.error('💡 Option 2 - Install build tools for compilation:');
67
+ console.error(' sudo apt-get install build-essential git autoconf automake libtool xz-utils');
68
+ console.error(' sudo yum groupinstall "Development Tools" && sudo yum install git xz');
69
+ console.error('');
70
+ console.error('🚫 SandboxBox cannot function without bubblewrap.');
71
+ process.exit(1);
64
72
  }
65
73
 
66
74
  async function downloadPreBuiltBinary(binaryPath) {
@@ -70,7 +78,7 @@ async function downloadPreBuiltBinary(binaryPath) {
70
78
  const possibleUrls = [
71
79
  // Alpine packages (HTTPS) - use the actual available version
72
80
  `https://dl-cdn.alpinelinux.org/alpine/v3.20/main/${arch}/bubblewrap-0.10.0-r0.apk`,
73
- // Try some common locations for pre-built binaries
81
+ // Try GitHub releases with different architectures
74
82
  `https://github.com/containers/bubblewrap/releases/download/v${BWRAP_VERSION}/bubblewrap-${BWRAP_VERSION}-${arch}.tar.xz`,
75
83
  `https://github.com/containers/bubblewrap/releases/download/v${BWRAP_VERSION}/bubblewrap-${BWRAP_VERSION}.tar.gz`,
76
84
  ];
@@ -200,46 +208,27 @@ async function buildFromSource(binaryPath) {
200
208
  const tmpDir = fs.mkdtempSync(path.join(process.env.TMPDIR || '/tmp', 'bwrap-build-'));
201
209
 
202
210
  try {
203
- // Download source tarball
204
- console.log('📥 Downloading bubblewrap source...');
205
- const tarball = `bubblewrap-${BWRAP_VERSION}.tar.xz`;
206
- const tarballPath = path.join(tmpDir, tarball);
207
- const url = `https://github.com/containers/bubblewrap/releases/download/v${BWRAP_VERSION}/${tarball}`;
208
-
209
- await new Promise((resolve, reject) => {
210
- const file = fs.createWriteStream(tarballPath);
211
-
212
- function download(url) {
213
- https.get(url, (response) => {
214
- // Handle redirects
215
- if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
216
- console.log(`🔄 Following redirect to: ${response.headers.location}`);
217
- download(response.headers.location);
218
- return;
219
- }
220
-
221
- if (response.statusCode !== 200) {
222
- reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));
223
- return;
224
- }
225
-
226
- response.pipe(file);
227
-
228
- file.on('finish', () => {
229
- file.close();
230
- resolve();
231
- });
232
- }).on('error', reject);
211
+ // Try to use system bubblewrap as fallback if available
212
+ try {
213
+ const systemBwrap = execSync('which bwrap', { encoding: 'utf8' }).trim();
214
+ if (systemBwrap && fs.existsSync(systemBwrap)) {
215
+ fs.copyFileSync(systemBwrap, binaryPath);
216
+ fs.chmodSync(binaryPath, 0o755);
217
+ console.log('✅ Using system bubblewrap:', systemBwrap);
218
+ return true;
233
219
  }
220
+ } catch (e) {
221
+ // System bwrap not found, continue with build
222
+ }
234
223
 
235
- download(url);
236
- });
237
-
238
- // Extract source
239
- console.log('📦 Extracting source...');
240
- execSync(`tar -xf "${tarballPath}" -C "${tmpDir}"`, { stdio: 'inherit' });
224
+ // Clone git repository for build files
225
+ console.log('📥 Downloading bubblewrap source from git...');
226
+ const sourceDir = path.join(tmpDir, 'bubblewrap');
241
227
 
242
- const sourceDir = path.join(tmpDir, `bubblewrap-${BWRAP_VERSION}`);
228
+ execSync(`
229
+ cd "${tmpDir}" &&
230
+ timeout 120 git clone --depth 1 --branch v${BWRAP_VERSION} https://github.com/containers/bubblewrap.git
231
+ `, { stdio: 'inherit' });
243
232
 
244
233
  // Check for required build tools
245
234
  const missingTools = [];
@@ -250,61 +239,37 @@ async function buildFromSource(binaryPath) {
250
239
  }
251
240
 
252
241
  try {
253
- execSync('which xz', { stdio: 'ignore' });
242
+ execSync('which git', { stdio: 'ignore' });
254
243
  } catch (e) {
255
- missingTools.push('xz');
256
- }
257
-
258
- try {
259
- execSync('which autoconf', { stdio: 'ignore' });
260
- } catch (e) {
261
- missingTools.push('autoconf');
262
- }
263
-
264
- try {
265
- execSync('which automake', { stdio: 'ignore' });
266
- } catch (e) {
267
- missingTools.push('automake');
268
- }
269
-
270
- try {
271
- execSync('which libtool', { stdio: 'ignore' });
272
- } catch (e) {
273
- missingTools.push('libtool');
244
+ missingTools.push('git');
274
245
  }
275
246
 
276
247
  if (missingTools.length > 0) {
277
248
  console.error(`❌ Missing build tools: ${missingTools.join(', ')}`);
278
249
  console.error('');
279
250
  console.error('💡 Install build tools:');
280
- console.error(' Ubuntu/Debian: sudo apt-get install build-essential autoconf automake libtool xz-utils');
281
- console.error(' CentOS/RHEL: sudo yum groupinstall "Development Tools" && sudo yum install xz');
251
+ console.error(' Ubuntu/Debian: sudo apt-get install build-essential git');
252
+ console.error(' CentOS/RHEL: sudo yum groupinstall "Development Tools" && sudo yum install git');
282
253
  console.error('');
283
254
  console.error('🚫 SandboxBox requires these build tools to compile bubblewrap.');
284
- return false; // Indicate build failed
255
+ return false;
285
256
  }
286
257
 
287
- // Configure and build
288
- console.log('⚙️ Configuring build...');
289
- execSync(`
290
- cd "${sourceDir}" &&
291
- ./configure --prefix="${tmpDir}/install" --disable-man
292
- `, { stdio: 'inherit' });
293
-
294
- console.log('🏗️ Compiling bubblewrap...');
295
- execSync(`
296
- cd "${sourceDir}" &&
297
- make -j$(nproc 2>/dev/null || echo 4)
298
- `, { stdio: 'inherit' });
299
-
300
- console.log('📦 Installing...');
301
- execSync(`
302
- cd "${sourceDir}" &&
303
- make install
304
- `, { stdio: 'inherit' });
258
+ // Simple compilation without autotools
259
+ console.log('🏗️ Compiling bubblewrap directly...');
260
+ try {
261
+ execSync(`
262
+ cd "${sourceDir}" &&
263
+ timeout 120 gcc -std=c99 -O2 -DHAVE_CONFIG_H=1 -o bwrap bubblewrap.c || \
264
+ gcc -std=c99 -O2 -o bwrap bubblewrap.c
265
+ `, { stdio: 'inherit' });
266
+ } catch (e) {
267
+ console.error('❌ Direct compilation failed');
268
+ return false;
269
+ }
305
270
 
306
271
  // Copy binary to final location
307
- const builtBinary = path.join(tmpDir, 'install', 'bin', 'bwrap');
272
+ const builtBinary = path.join(sourceDir, 'bwrap');
308
273
  if (fs.existsSync(builtBinary)) {
309
274
  fs.copyFileSync(builtBinary, binaryPath);
310
275
  fs.chmodSync(binaryPath, 0o755);
@@ -313,15 +278,15 @@ async function buildFromSource(binaryPath) {
313
278
  // Test the binary
314
279
  const version = execSync(`"${binaryPath}" --version`, { encoding: 'utf8' });
315
280
  console.log(`🎯 Built: ${version.trim()}`);
316
- return true; // Build succeeded
281
+ return true;
317
282
  } else {
318
283
  console.log('❌ Built binary not found');
319
- return false; // Build failed
284
+ return false;
320
285
  }
321
286
 
322
287
  } catch (error) {
323
288
  console.log(`❌ Build from source failed: ${error.message}`);
324
- return false; // Build failed
289
+ return false;
325
290
  } finally {
326
291
  // Cleanup
327
292
  fs.rmSync(tmpDir, { recursive: true, force: true });
@@ -335,64 +300,4 @@ downloadAndBuild().catch(error => {
335
300
  console.error('🚫 SandboxBox cannot function without bubblewrap.');
336
301
  console.error(' Please install build tools and try again.');
337
302
  process.exit(1);
338
- });
339
-
340
- function createMinimalBubblewrap(binaryPath) {
341
- console.log('🔧 Creating minimal bubblewrap fallback...');
342
-
343
- const minimalBwrap = `#!/bin/bash
344
- # Minimal bubblewrap fallback for SandboxBox
345
- # This provides basic namespace isolation functionality
346
-
347
- # Handle --version flag for compatibility
348
- if [[ "$1" == "--version" ]]; then
349
- echo "bubblewrap 0.11.0 (minimal fallback for SandboxBox)"
350
- exit 0
351
- fi
352
-
353
- # Handle --help flag
354
- if [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]]; then
355
- echo "bubblewrap - minimal fallback version"
356
- echo ""
357
- echo "⚠️ This is a minimal fallback for SandboxBox"
358
- echo "💡 For full functionality, install bubblewrap:"
359
- echo " sudo apt-get install bubblewrap"
360
- echo ""
361
- echo "Usage: bwrap [options] -- command [args]"
362
- exit 0
363
- fi
364
-
365
- echo "⚠️ Using minimal bubblewrap fallback"
366
- echo "💡 For full functionality, install bubblewrap:"
367
- echo " sudo apt-get install bubblewrap"
368
- echo ""
369
-
370
- # Filter out bubblewrap-specific options that unshare doesn't support
371
- ARGS=()
372
- for arg in "$@"; do
373
- case "$arg" in
374
- --ro-bind|--bind|--dev-bind|--proc|--tmpfs|--symlink|--dir|--file|--setenv|--die-with-parent|--new-session|--share-net|--unshare-net|--unshare-pid|--unshare-ipc|--unshare-uts|--unshare-cgroup|--unshare-user)
375
- # Skip bubblewrap-specific options
376
- ;;
377
- *)
378
- ARGS+=("$arg")
379
- ;;
380
- esac
381
- done
382
-
383
- # Basic namespace isolation using unshare
384
- exec unshare \\
385
- --pid \\
386
- --mount \\
387
- --uts \\
388
- --ipc \\
389
- --net \\
390
- --fork \\
391
- --mount-proc \\
392
- "\${ARGS[@]}"
393
- `;
394
-
395
- fs.writeFileSync(binaryPath, minimalBwrap);
396
- fs.chmodSync(binaryPath, 0o755);
397
- console.log('✅ Created minimal bubblewrap fallback');
398
- }
303
+ });