// Guard rules for shell commands, focused on inline interpreter scripts. import test from 'node:test' import assert from 'node:assert/strict' import { shellViolation, inlineScriptViolation } from '../index.js' const ALLOW = [ // harmless computation one-liners `node -e "console.log(1+1)"`, `node -p "2**10"`, `node --eval 'console.log([1,2,3].map(x => x * 2))'`, `node --print="JSON.stringify({a: 1})"`, `node -pe "Math.max(3, 7)"`, `python3 -c "print(2**10)"`, `python3 -c 'print(sum(range(100)))'`, `ruby -e 'puts [1,2,3].sum'`, `perl -e 'print 6*7, "\\n"'`, `node -e 'console.log(JSON.parse(\`{"a":1}\`).a)'`, // running files / tools is a normal command, not an inline script 'node --test test/', 'node build.mjs', 'node --check index.js', 'python3 manage.py migrate', 'node --version', 'python3 --version', // unrelated commands 'git status', 'npm test 2>&1 | tail -5', ] const BLOCK = [ // the reported gap `node --input-type=module --eval "import fs from 'node:fs'; fs.readFileSync('a')"`, `node --input-type=module -e "import('node:fs').then(m => m.writeFileSync('a', 'b'))"`, // direct file / process access `node -e "require('fs').writeFileSync('a', 'b')"`, `node -e "require('child_process').execSync('cat f')"`, `node -p "process.mainModule.require('fs')"`, `node -e "fs['write'+'File']('a','b')"`, `node -e "globalThis['req'+'uire']('fs')"`, `node -e "this.constructor.constructor('return process')()"`, `node -e "eval('requ'+'ire')('fs')"`, `node -e "new Function('return process')()"`, `node -e "fetch('http://x')"`, `python3 -c "open('f','w').write('x')"`, `python3 -c "import os; os.remove('f')"`, `python3 -c "__import__('os').system('ls')"`, `python3 -c "print(().__class__.__bases__[0].__subclasses__())"`, `ruby -e "File.write('x', 1)"`, 'ruby -e "puts `ls`"', `perl -e 'open(F, ">x")'`, `deno eval "Deno.writeTextFileSync('x','y')"`, `bun -e "Bun.write('x','y')"`, `php -r "file_put_contents('x','y');"`, // scripts we cannot inspect 'echo "require(1)" | node', 'cat script.js | node -', 'node - < script.js', 'python3 - < s.py', // wrapped forms `env FOO=1 node -e "require('fs')"`, `sudo node -e "require('fs')"`, `/usr/bin/node -e "require('fs')"`, `ls && node -e "require('fs')"`, ] test('harmless inline one-liners and normal commands are allowed', () => { for (const c of ALLOW) assert.equal(shellViolation(c), null, `should allow: ${c}`) }) test('file/process/network-capable or uninspectable inline scripts are blocked', () => { for (const c of BLOCK) assert.ok(inlineScriptViolation(c) || shellViolation(c), `should block: ${c}`) }) test('denial message points at the right tools', () => { const m = shellViolation(`node -e "require('fs').readFileSync('a')"`) assert.match(m, /read\/grep\/edit/) assert.match(m, /computation-only one-liners are fine/) })