| name | ast-injection-scanner |
| description | Statically scan agent-generated JavaScript and shell scripts for dangerous patterns using AST analysis (acorn/swc). Detect eval(), process.env access, dynamic require(), child_process usage, and path traversal before code execution. |
| origin | acorn (MIT), swc (Apache-2.0), ESTree spec, OWASP Code Injection Cheat Sheet |
| license | Apache-2.0 |
| version | 1.0.0 |
| compatibility | claude-sonnet-4-6, claude-opus-4-7 |
AST Injection Scanner
Parse agent-generated code into an Abstract Syntax Tree and walk every node looking for dangerous call patterns — before any line is executed.
When to Use
- Agent system that generates and hot-loads JS code at runtime
- Validating shell scripts produced by an agent before executing them
- Building a pre-commit hook that blocks dangerous code patterns
- Implementing YAMTAM sovereign-runtime-law (rule 51) AST gate
Do NOT use for
- Linting developer code (use ESLint with security plugins instead)
- Python/Ruby code (use language-specific AST tools: ast module, RuboCop)
- Performance-critical paths where AST parse overhead is unacceptable
acorn-based Scanner
import { parse } from 'acorn';
const BLOCKED_CALLS = new Set(['eval', 'exec', 'execSync', 'execFile', 'spawnSync', 'fork']);
const BLOCKED_MEMBERS = [
{ object: 'process', property: 'env' },
{ object: 'child_process', property: null },
{ object: 'fs', property: 'writeFileSync' },
{ object: 'fs', property: 'unlinkSync' },
];
function scanAST(source, filename = 'agent-generated') {
const ast = parse(source, {
ecmaVersion: 2022,
sourceType: 'module',
locations: true,
});
const violations = [];
function walk(node) {
if (!node || typeof node !== 'object') return;
if (node. === ) {
name = node.?. ?? node.?.?.;
(.(name)) {
violations.({ : , name, : node.?.. });
}
}
(node. === ) {
obj = node.?.;
prop = node.?.;
( blocked ) {
(obj === blocked. && (blocked. === || prop === blocked.)) {
violations.({ : , : , : node.?.. });
}
}
}
( key .(node)) {
([,,,].(key)) ;
child = node[key];
(.(child)) child.(walk);
(child?.) (child);
}
}
(ast);
{ : violations. === , violations, filename };
}
Shell Script Scanner (Regex Fallback)
#!/usr/bin/env bash
scan_shell() {
local file="$1"
local violations=()
grep -nE '(eval |`.*`|\$\(|\bexec\b|LD_PRELOAD|curl\s+.*\|\s*bash|wget\s+.*\|\s*sh)' "$file" \
| while IFS=: read -r line content; do
echo "VIOLATION line ${line}: ${content}" >&2
violations+=("line:${line}")
done
[[ ${#violations[@]} -gt 0 ]] && return 3
return 0
}
scan_shell "$1"
Dynamic require() Detection
function isDynamicRequire(node) {
if (node.type !== 'CallExpression') return false;
if (node.callee?.name !== 'require') return false;
const arg = node.arguments?.[0];
return !arg || arg.type !== 'Literal';
}
Pre-execution Pipeline
async function safeExecute(agentId, generatedCode) {
const { safe, violations } = scanAST(generatedCode, `${agentId}-generated`);
if (!safe) {
swarmRouter.penalize(agentId, 15, 'AST_VIOLATION');
throw new Error(`AST blocked: ${violations[0].type} at line ${violations[0].line}`);
}
const sig = signArtifact(generatedCode);
return executeInSandbox(generatedCode, { signature: sig });
}
Anti-Fake-Pass Checklist