- Implemented a validation function to check for banned commands and dangerous patterns.
- Added checks for potential shell injection attempts in command and arguments. - Security validation is conditionally enabled based on environment variable CUSTOM_MCP_SECURITY_CHECK.
This commit is contained in:
parent
bbb03b7b3b
commit
8e7a3a8b37
|
|
@ -5,6 +5,101 @@ import { getVars, prepareSandboxVars } from '../../../../src/utils'
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import hash from 'object-hash'
|
import hash from 'object-hash'
|
||||||
|
|
||||||
|
// List of dangerous commands that are banned for security reasons
|
||||||
|
const BANNED_COMMANDS = [
|
||||||
|
'sh',
|
||||||
|
'bash',
|
||||||
|
'zsh',
|
||||||
|
'fish',
|
||||||
|
'csh',
|
||||||
|
'tcsh',
|
||||||
|
'ksh',
|
||||||
|
'dash',
|
||||||
|
'/bin/sh',
|
||||||
|
'/bin/bash',
|
||||||
|
'/bin/zsh',
|
||||||
|
'/bin/fish',
|
||||||
|
'/bin/csh',
|
||||||
|
'/bin/tcsh',
|
||||||
|
'/bin/ksh',
|
||||||
|
'/bin/dash',
|
||||||
|
'/usr/bin/sh',
|
||||||
|
'/usr/bin/bash',
|
||||||
|
'/usr/bin/zsh',
|
||||||
|
'/usr/bin/fish',
|
||||||
|
'/usr/bin/csh',
|
||||||
|
'/usr/bin/tcsh',
|
||||||
|
'/usr/bin/ksh',
|
||||||
|
'/usr/bin/dash',
|
||||||
|
'cmd',
|
||||||
|
'cmd.exe',
|
||||||
|
'powershell',
|
||||||
|
'powershell.exe',
|
||||||
|
'pwsh',
|
||||||
|
'pwsh.exe',
|
||||||
|
'perl',
|
||||||
|
'ruby',
|
||||||
|
'php',
|
||||||
|
'eval',
|
||||||
|
'exec',
|
||||||
|
'system'
|
||||||
|
]
|
||||||
|
|
||||||
|
// Additional dangerous command patterns to check
|
||||||
|
const DANGEROUS_PATTERNS = [
|
||||||
|
/^\/bin\//,
|
||||||
|
/^\/usr\/bin\//,
|
||||||
|
/^\/usr\/local\/bin\//,
|
||||||
|
/^\/sbin\//,
|
||||||
|
/^\/usr\/sbin\//,
|
||||||
|
/\.exe$/i,
|
||||||
|
/\.bat$/i,
|
||||||
|
/\.cmd$/i,
|
||||||
|
/\.ps1$/i,
|
||||||
|
/\.sh$/i
|
||||||
|
]
|
||||||
|
|
||||||
|
function validateCommand(command: string): void {
|
||||||
|
if (!command || typeof command !== 'string') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedCommand = command.toLowerCase().trim()
|
||||||
|
|
||||||
|
// Check against banned commands list
|
||||||
|
for (const bannedCmd of BANNED_COMMANDS) {
|
||||||
|
if (
|
||||||
|
normalizedCommand === bannedCmd.toLowerCase() ||
|
||||||
|
normalizedCommand.endsWith(`/${bannedCmd.toLowerCase()}`) ||
|
||||||
|
normalizedCommand.endsWith(`\\${bannedCmd.toLowerCase()}`)
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`Security Error: Command "${command}" is banned for security reasons. Shell access and executable commands are not allowed.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check against dangerous patterns
|
||||||
|
for (const pattern of DANGEROUS_PATTERNS) {
|
||||||
|
if (pattern.test(normalizedCommand)) {
|
||||||
|
throw new Error(`Security Error: Command "${command}" matches a dangerous pattern and is not allowed for security reasons.`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional checks for potential shell injection attempts
|
||||||
|
if (
|
||||||
|
normalizedCommand.includes('&&') ||
|
||||||
|
normalizedCommand.includes('||') ||
|
||||||
|
normalizedCommand.includes(';') ||
|
||||||
|
normalizedCommand.includes('|') ||
|
||||||
|
normalizedCommand.includes('`') ||
|
||||||
|
normalizedCommand.includes('$(') ||
|
||||||
|
normalizedCommand.includes('${')
|
||||||
|
) {
|
||||||
|
throw new Error(`Security Error: Command "${command}" contains potentially dangerous shell operators and is not allowed.`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const mcpServerConfig = `{
|
const mcpServerConfig = `{
|
||||||
"command": "npx",
|
"command": "npx",
|
||||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files"]
|
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files"]
|
||||||
|
|
@ -169,6 +264,35 @@ class Custom_MCP implements INode {
|
||||||
serverParams = JSON.parse(serverParamsString)
|
serverParams = JSON.parse(serverParamsString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Security validation: Check for dangerous commands
|
||||||
|
// TODO: To be removed and only allow Remote MCP for Cloud
|
||||||
|
if (serverParams?.command && process.env.CUSTOM_MCP_SECURITY_CHECK === 'true') {
|
||||||
|
validateCommand(serverParams.command)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also validate any commands in args that might be suspicious
|
||||||
|
// TODO: To be removed and only allow Remote MCP for Cloud
|
||||||
|
if (serverParams?.args && Array.isArray(serverParams.args) && process.env.CUSTOM_MCP_SECURITY_CHECK === 'true') {
|
||||||
|
for (const arg of serverParams.args) {
|
||||||
|
if (typeof arg === 'string') {
|
||||||
|
// Check if any argument looks like it's trying to execute a shell command
|
||||||
|
const suspiciousArg = arg.toLowerCase().trim()
|
||||||
|
if (
|
||||||
|
suspiciousArg.startsWith('/bin/') ||
|
||||||
|
suspiciousArg.startsWith('/usr/bin/') ||
|
||||||
|
suspiciousArg.includes('sh') ||
|
||||||
|
suspiciousArg.includes('bash') ||
|
||||||
|
suspiciousArg.includes('cmd') ||
|
||||||
|
suspiciousArg.includes('powershell')
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`Security Error: Argument "${arg}" contains potentially dangerous command references and is not allowed.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Compatible with stdio and SSE
|
// Compatible with stdio and SSE
|
||||||
let toolkit: MCPToolkit
|
let toolkit: MCPToolkit
|
||||||
if (serverParams?.command === undefined) {
|
if (serverParams?.command === undefined) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue