@light-merlin-dark/vssh
Version:
MCP-native SSH proxy for AI agents. CLI & MCP Server, plugin system, AI safety guards.
127 lines • 7.37 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandGuard = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const config_1 = require("../config");
class CommandGuard {
static checkCommand(command) {
const reasons = [];
let rule;
// Check dangerous patterns
for (const { pattern, reason } of this.DANGEROUS_PATTERNS) {
if (pattern.test(command)) {
reasons.push(reason);
rule = pattern.toString();
break;
}
}
// Check suspicious patterns
for (const { pattern, reason } of this.SUSPICIOUS_PATTERNS) {
if (pattern.test(command)) {
reasons.push(`⚠️ WARNING: ${reason}`);
if (!rule)
rule = pattern.toString();
}
}
return {
isBlocked: reasons.length > 0 && !reasons[0].startsWith('⚠️'),
reasons,
rule
};
}
static displayBlockedMessage(command, result) {
console.error('\n🚫 COMMAND BLOCKED FOR SAFETY REASONS\n');
console.error(`Command: ${command}`);
console.error(`Reason: ${result.reasons[0]}`);
console.error('\nThis command has been blocked to prevent potential system damage.');
console.error('If you believe this is a false positive, please review the command carefully.\n');
}
static logBlockedCommand(command, result) {
const timestamp = new Date().toISOString();
const logEntry = `[${timestamp}] BLOCKED: ${command}\nReason: ${result.reasons.join(', ')}\nRule: ${result.rule}\n${'='.repeat(80)}\n`;
const logPath = path.join(config_1.LOGS_PATH, 'blocked_commands.log');
fs.appendFileSync(logPath, logEntry);
}
}
exports.CommandGuard = CommandGuard;
CommandGuard.DANGEROUS_PATTERNS = [
// Filesystem destruction - Enhanced patterns
{ pattern: /(?:^|\s)(?:sudo\s+)?rm\s+(?:.*\s+)?-rf\s+\/(?:\s|$)/, reason: 'Attempting to delete root filesystem' },
{ pattern: /(?:^|\s)(?:sudo\s+)?rm\s+(?:.*\s+)?-rf\s+\/\*/, reason: 'Attempting to delete all files in root' },
{ pattern: /(?:^|\s)(?:sudo\s+)?rm\s+(?:.*\s+)?-rf\s+~\/\*/, reason: 'Attempting to delete all files in home directory' },
{ pattern: /(?:^|\s)(?:sudo\s+)?rm\s+.*--no-preserve-root.*\/(?:\s|$)/, reason: 'Root deletion with no-preserve-root flag' },
{ pattern: /(?:^|\s)(?:sudo\s+)?rm\s+(?:.*\s+)?-rf\s+\/(?:etc|var|usr|bin|sbin|lib|boot|dev|sys|proc)(?:\s|\/|$)/i, reason: 'Attempting to delete critical system directory' },
{ pattern: /(?:^|\s)(?:sudo\s+)?rm\s+(?:.*\s+)?-rf\s+\/data\//, reason: 'Attempting to delete data directory' },
// Disk operations
{ pattern: /dd\s+.*of=\/dev\/[sh]d[a-z](?:\d|$)/, reason: 'Direct disk write operations are dangerous' },
{ pattern: /mkfs\.[a-z0-9]+\s+\/dev\//, reason: 'Filesystem formatting commands are dangerous' },
{ pattern: />\s*\/dev\/[sh]d[a-z]/, reason: 'Direct disk write operations are dangerous' },
{ pattern: /fdisk\s+\/dev\//, reason: 'Disk partitioning commands are dangerous' },
{ pattern: /parted\s+.*\/dev\//, reason: 'Disk partitioning commands are dangerous' },
// Docker destruction
{ pattern: /docker\s+system\s+prune.*(?:-a|--all).*(?:--volumes|-v)/, reason: 'Mass Docker cleanup with volumes is dangerous' },
{ pattern: /docker\s+system\s+prune.*(?:--volumes|-v).*(?:-a|--all)/, reason: 'Mass Docker cleanup with volumes is dangerous' },
{ pattern: /docker\s+volume\s+prune.*(?:-f|--force)/, reason: 'Forced Docker volume deletion is dangerous' },
{ pattern: /docker\s+compose\s+down.*--volumes/, reason: 'Docker compose with volume deletion is dangerous' },
{ pattern: /docker-compose\s+down.*--volumes/, reason: 'Docker compose with volume deletion is dangerous' },
// Service disruption
{ pattern: /(?:^|\s)(?:sudo\s+)?systemctl\s+(?:stop|disable|mask)\s+(?:docker|ssh|sshd|vssh)(?:\s|$)/, reason: 'Stopping critical services is dangerous' },
{ pattern: /(?:^|\s)(?:sudo\s+)?service\s+(?:docker|ssh|sshd|vssh)\s+(?:stop|disable)/, reason: 'Stopping critical services is dangerous' },
// Network disruption
{ pattern: /iptables\s+-F/, reason: 'Flushing firewall rules is dangerous' },
{ pattern: /iptables\s+--flush/, reason: 'Flushing firewall rules is dangerous' },
{ pattern: /ufw\s+(?:disable|--force\s+reset)/, reason: 'Disabling firewall is dangerous' },
// System files
{ pattern: />\s*\/etc\/(?:passwd|shadow|group|sudoers)/, reason: 'Overwriting critical system files' },
{ pattern: /(?:^|\s)(?:sudo\s+)?rm\s+.*\/etc\/(?:passwd|shadow|group|sudoers)/, reason: 'Deleting critical system files' },
{ pattern: /(?:^|\s)(?:sudo\s+)?truncate\s+.*\/etc\/(?:passwd|shadow|group|sudoers)/, reason: 'Truncating critical system files' },
// System shutdown/reboot
{ pattern: /(?:^|\s)(?:sudo\s+)?(?:shutdown|poweroff|halt|reboot|init\s+0|init\s+6)(?:\s|$)/, reason: 'System shutdown/reboot commands are dangerous' },
// Permissions
{ pattern: /chmod\s+(?:-R\s+)?777\s+\//, reason: 'Making entire filesystem world-writable' },
{ pattern: /chown\s+(?:-R\s+)?.*:.*\s+\/(?:\s|$)/, reason: 'Changing ownership of entire filesystem' },
// Fork bombs and malicious patterns
{ pattern: /:\s*\(\)\s*{\s*:\s*\|\s*:\s*&\s*}\s*;?\s*:/, reason: 'Fork bomb detected' },
{ pattern: /\$\(.*\)\s*{\s*\$\(.*\)\|.*&\s*}/, reason: 'Potential fork bomb pattern' },
];
CommandGuard.SUSPICIOUS_PATTERNS = [
{ pattern: /curl\s+.*\|\s*(?:bash|sh)/, reason: 'Downloading and executing scripts directly' },
{ pattern: /wget\s+.*\|\s*(?:bash|sh)/, reason: 'Downloading and executing scripts directly' },
{ pattern: /eval\s+.*curl/, reason: 'Evaluating downloaded content' },
{ pattern: /eval\s+.*wget/, reason: 'Evaluating downloaded content' },
];
//# sourceMappingURL=command-guard.js.map