neurondb 1.0.2 → 1.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neurondb",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "N-Bash — Interactive SNL terminal and remote bash executor for NeuronDB",
5
5
  "bin": {
6
6
  "neuron": "./bin/cli.js",
package/src/config.js CHANGED
@@ -28,6 +28,11 @@ export const BLOCKED_COMMANDS = [
28
28
  'iptables', 'ip6tables', 'nft', 'firewall-cmd',
29
29
  'systemctl', 'service', 'journalctl',
30
30
  'fdisk', 'parted', 'mkswap', 'swapon', 'swapoff',
31
+ // Interactive commands that hang (no stdout, wait for input)
32
+ 'top', 'htop', 'btop', 'vi', 'vim', 'nvim', 'nano', 'pico', 'emacs',
33
+ 'less', 'more', 'man', 'watch', 'tail -f', 'ssh', 'telnet', 'ftp',
34
+ 'python', 'python3', 'node', 'irb', 'ruby', 'lua', // REPLs without args
35
+ 'mysql', 'psql', 'mongo', 'redis-cli', // DB shells without args
31
36
  ];
32
37
 
33
38
  /** Blocked path prefixes — prevent access outside sandbox */
package/src/executor.js CHANGED
@@ -10,6 +10,7 @@ import { validateCommand } from './sandbox.js';
10
10
  * Execute a bash command in the sandbox.
11
11
  * @param {string} command - The command to execute
12
12
  * @param {string} homeDir - The sandbox home directory (cwd)
13
+ * @param {number} [timeoutMs] - Timeout in milliseconds
13
14
  * @returns {Promise<{stdout: string, stderr: string, exit_code: number, duration_ms: number}>}
14
15
  */
15
16
  export function executeCommand(command, homeDir, timeoutMs) {
@@ -27,21 +28,22 @@ export function executeCommand(command, homeDir, timeoutMs) {
27
28
  }
28
29
 
29
30
  const startTime = Date.now();
31
+ const timeout = timeoutMs || EXEC_TIMEOUT_MS;
30
32
 
31
33
  const env = {
32
34
  HOME: homeDir,
33
35
  PATH: process.env.PATH || '/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin',
34
- TERM: process.env.TERM || 'xterm-256color',
36
+ TERM: 'dumb', // Force non-interactive mode (prevents curses, color escapes)
35
37
  LANG: process.env.LANG || 'en_US.UTF-8',
36
38
  NODE_ENV: process.env.NODE_ENV || 'production',
37
39
  };
38
40
 
39
- execFile('/bin/bash', ['-c', command], {
41
+ const child = execFile('/bin/bash', ['-c', command], {
40
42
  cwd: homeDir,
41
- timeout: timeoutMs || EXEC_TIMEOUT_MS,
43
+ timeout,
42
44
  maxBuffer: EXEC_MAX_BUFFER,
43
45
  env,
44
- killSignal: 'SIGTERM',
46
+ killSignal: 'SIGKILL', // Use SIGKILL — SIGTERM doesn't stop interactive commands
45
47
  }, (error, stdout, stderr) => {
46
48
  const duration_ms = Date.now() - startTime;
47
49
  let exit_code = 0;
@@ -49,7 +51,7 @@ export function executeCommand(command, homeDir, timeoutMs) {
49
51
  if (error) {
50
52
  exit_code = error.code != null ? error.code : (error.signal ? 128 : 1);
51
53
  if (error.killed) {
52
- stderr = (stderr || '') + '\nProcess killed (timeout or memory limit)';
54
+ stderr = (stderr || '') + '\nProcess killed (timeout reached)';
53
55
  exit_code = 137;
54
56
  }
55
57
  }
@@ -61,5 +63,12 @@ export function executeCommand(command, homeDir, timeoutMs) {
61
63
  duration_ms,
62
64
  });
63
65
  });
66
+
67
+ // Safety net: force kill if still alive after timeout + 5s grace
68
+ const safetyTimer = setTimeout(() => {
69
+ try { child.kill('SIGKILL'); } catch {}
70
+ }, timeout + 5000);
71
+
72
+ child.on('exit', () => clearTimeout(safetyTimer));
64
73
  });
65
74
  }