godcrm/backend/services/CommandClassifier.js
GOD CRM Release f89e074dd1
Some checks failed
CI / Lint / Typecheck / Test / Build (push) Has been cancelled
CI / PostgreSQL Integration Tests (push) Has been cancelled
GOD CRM — public scrubbed snapshot
Governed substrate for autonomous agents: scoped identity (passports),
audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
2026-08-10 04:01:45 +03:00

124 lines
3.4 KiB
JavaScript

/**
* CommandClassifier - ADR-076: Terminal Command Risk Classification
*
* Classifies shell commands into risk levels:
* - safe: read-only commands (ls, cat, grep, git status)
* - medium: write commands that are reversible (git commit, npm install, mkdir)
* - dangerous: destructive/irreversible commands (rm -rf, sudo, git push --force)
*/
import { logger } from '../utils/logger.js';
/** @typedef {'safe' | 'medium' | 'dangerous'} RiskLevel */
/**
* Patterns for dangerous commands
* These require explicit approval before execution
*/
const DANGEROUS_PATTERNS = [
// Destructive file operations
/\brm\s+(-[a-zA-Z]*r[a-zA-Z]*f|--recursive|--force)/,
/\brm\s+-rf\b/,
// Elevated privileges
/\bsudo\b/,
/\bsu\s+-?\s*$/,
/\bsu\s+\w/,
// Git destructive
/\bgit\s+push\s+.*--force\b/,
/\bgit\s+push\s+-f\b/,
/\bgit\s+reset\s+--hard\b/,
/\bgit\s+clean\s+-[a-zA-Z]*f/,
// Database destructive
/\bDROP\s+(TABLE|DATABASE|SCHEMA)\b/i,
/\bTRUNCATE\b/i,
/\bDELETE\s+FROM\s+\w+\s*;?\s*$/i,
// System control
/\bsystemctl\s+(restart|stop|disable)\b/,
/\bservice\s+\w+\s+(restart|stop)\b/,
/\bkill\s+(-9|-KILL)\b/,
/\bkillall\b/,
/\bpkill\b/,
// Publishing/deploying
/\bnpm\s+publish\b/,
/\bdeploy\b/,
// Permissions
/\bchmod\s+777\b/,
/\bchown\s+-R\b/,
// Shell bombs and pipes to shell
/:\s*\(\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;/,
/\bcurl\b.*\|\s*(bash|sh|zsh)\b/,
/\bwget\b.*\|\s*(bash|sh|zsh)\b/,
// Format/wipe
/\bmkfs\b/,
/\bdd\s+if=/,
].filter(Boolean);
/**
* Patterns for medium-risk commands
* These execute immediately but are logged
*/
const MEDIUM_PATTERNS = [
// Git write operations
/\bgit\s+(commit|push|merge|rebase|checkout|branch\s+-[dD])\b/,
/\bgit\s+stash\s+(drop|clear)\b/,
// Package management
/\bnpm\s+(install|update|uninstall|ci)\b/,
/\byarn\s+(add|remove|upgrade)\b/,
/\bpnpm\s+(install|add|remove|update)\b/,
// File write operations
/\bmv\b/,
/\bcp\s+-r\b/,
/\bmkdir\b/,
/\btouch\b/,
// Text processing that modifies files
/\bsed\s+-i\b/,
/\bawk\b.*>>/,
// File write redirects
/>\s*[^>]/,
/>>/,
// Build operations
/\bnpm\s+run\s+build\b/,
/\bnpx\b/,
];
/**
* Classify a shell command by risk level
* @param {string} command - The command to classify
* @returns {{ riskLevel: RiskLevel, matchedPattern: string | null }}
*/
export function classifyCommand(command) {
if (!command || typeof command !== 'string') {
return { riskLevel: 'safe', matchedPattern: null };
}
const trimmed = command.trim();
// Check dangerous first
for (const pattern of DANGEROUS_PATTERNS) {
if (pattern && pattern.test(trimmed)) {
logger.debug({ command: trimmed, pattern: pattern.toString() }, 'Command classified as dangerous');
return { riskLevel: 'dangerous', matchedPattern: pattern.toString() };
}
}
// Check medium
for (const pattern of MEDIUM_PATTERNS) {
if (pattern.test(trimmed)) {
logger.debug({ command: trimmed, pattern: pattern.toString() }, 'Command classified as medium');
return { riskLevel: 'medium', matchedPattern: pattern.toString() };
}
}
// Default: safe
return { riskLevel: 'safe', matchedPattern: null };
}
/**
* Check if a command needs approval
* @param {string} command
* @returns {boolean}
*/
export function needsApproval(command) {
const { riskLevel } = classifyCommand(command);
return riskLevel === 'dangerous';
}