- 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 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 = `{
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files"]
|
||||
|
|
@ -169,6 +264,35 @@ class Custom_MCP implements INode {
|
|||
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
|
||||
let toolkit: MCPToolkit
|
||||
if (serverParams?.command === undefined) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue