/** * Tool Sandbox PoC (Gen 2 - Production Tooling) * * This script proves that the execution environment can physically handle * invoking actual production-grade tooling constraints (WASM for Tree-sitter * and Deno.Command for Semgrep). * * Dependencies required on host system for this PoC: * 1. Semgrep: `sudo pip3 install semgrep --break-system-packages` * 2. Tree-sitter: `npm install web-tree-sitter tree-sitter-javascript` */ import { join, dirname, fromFileUrl } from "https://deno.land/std@0.224.0/path/mod.ts"; import * as webTreeSitter from "npm:web-tree-sitter@0.26.13"; const Parser = webTreeSitter.default || webTreeSitter.Parser; const currentDir = dirname(fromFileUrl(import.meta.url)); const TEMP_FILE = join(currentDir, "dummy_target.js"); const DUMMY_CODE = ` function vulnerableQuery(userInput) { const query = "SELECT * FROM users WHERE name = '" + userInput + "'"; db.execute(query); } `; async function testTreeSitter() { console.log("\n--- Testing Tree-sitter (WASM) ---"); try { // web-tree-sitter requires initialization to load the base wasm await Parser.init(); // Explicitly load the JavaScript language grammar WASM using a direct path // In a real environment, this might be copied to a known static directory. // For this PoC, we point directly to the npm installation path. const rootDir = dirname(dirname(currentDir)); // Root of repo const wasmPath = join(rootDir, "node_modules", "tree-sitter-javascript", "tree-sitter-javascript.wasm"); console.log(`[Sandbox] Loading Language WASM from: ${wasmPath}`); const wasmBytes = await Deno.readFile(wasmPath); const Lang = await webTreeSitter.Language.load(wasmBytes); const parser = new Parser(); parser.setLanguage(Lang); const tree = parser.parse(DUMMY_CODE); console.log("[Sandbox] Successfully parsed syntax tree!"); console.log(`[Sandbox] Root Node Type: ${tree.rootNode.type}`); console.log(`[Sandbox] Extracted Functions: ${tree.rootNode.children.filter(n => n.type === 'function_declaration').map(n => n.childForFieldName('name')?.text).join(', ')}`); return true; } catch (error) { console.error("❌ Tree-sitter WASM execution failed:", error.message); console.error("Please ensure you ran: `npm install web-tree-sitter tree-sitter-javascript`"); return false; } } async function testSemgrep() { console.log("\n--- Testing Semgrep (Binary) ---"); try { // Write out dummy file for semgrep to scan await Deno.writeTextFile(TEMP_FILE, DUMMY_CODE); // Define a basic semgrep rule directly via CLI flag to detect our dummy issue const command = new Deno.Command("semgrep", { args: [ "--quiet", "--json", "--lang", "javascript", "-e", '"$SELECT ... " + $INPUT', TEMP_FILE ], stdout: "piped", stderr: "piped", }); const { code, stdout, stderr } = await command.output(); const decoder = new TextDecoder(); if (code !== 0 && code !== 1) { // 1 means findings found, 0 means no findings. Other codes are errors. console.error("❌ Semgrep execution returned error code:", code); console.error(decoder.decode(stderr)); return false; } const outputString = decoder.decode(stdout); const jsonResult = JSON.parse(outputString); console.log("[Sandbox] Successfully executed native semgrep binary!"); console.log(`[Sandbox] Vulnerabilities found: ${jsonResult.results.length}`); if (jsonResult.results.length > 0) { console.log(`[Sandbox] Details: ${jsonResult.results[0].extra.message} (Line ${jsonResult.results[0].start.line})`); } return true; } catch (error) { console.error("❌ Semgrep binary execution failed:", error.message); console.error("Please ensure Semgrep is installed: `sudo pip3 install semgrep --break-system-packages`"); return false; } finally { try { await Deno.remove(TEMP_FILE); } catch { // ignore } } } async function runSandbox() { console.log("Starting Gen 2 Tool Sandbox (Production Dependencies)\n"); const tsSuccess = await testTreeSitter(); const sgSuccess = await testSemgrep(); if (tsSuccess && sgSuccess) { console.log("\n✅ Gen 2 Sandbox execution completed successfully. Physical tools verified."); } else { console.error("\n❌ Gen 2 Sandbox failed due to missing or malfunctioning host dependencies."); Deno.exit(1); } } if (import.meta.main) { runSandbox().catch(console.error); }