mirror of
https://github.com/FlowiseAI/Flowise.git
synced 2026-10-12 02:02:17 +00:00
Additional Improvements to MCP Server Config security (#5943)
This commit is contained in:
@@ -33,6 +33,22 @@ describe('MCP Security Validations', () => {
|
||||
}).toThrow("Argument '-y' is not allowed for command 'npx'")
|
||||
})
|
||||
|
||||
it('should block --yes flag', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('npx', ['--yes', 'https://test-malicious-download.com'])
|
||||
}).toThrow("Argument '--yes' is not allowed for command 'npx'")
|
||||
})
|
||||
|
||||
it('should block --node-options flag', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('npx', ['--node-options', '--eval malicious'])
|
||||
}).toThrow("Argument '--node-options' is not allowed for command 'npx'")
|
||||
|
||||
expect(() => {
|
||||
validateCommandFlags('npx', ['--node-options=--eval malicious'])
|
||||
}).toThrow("contains flag '--node-options'")
|
||||
})
|
||||
|
||||
it('should block case variations', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('npx', ['-C', 'command'])
|
||||
@@ -83,6 +99,42 @@ describe('MCP Security Validations', () => {
|
||||
}).toThrow("Argument '--inspect-brk' is not allowed for command 'node'")
|
||||
})
|
||||
|
||||
it('should block -r/--require flags', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('node', ['-r', 'malicious-module'])
|
||||
}).toThrow("Argument '-r' is not allowed for command 'node'")
|
||||
|
||||
expect(() => {
|
||||
validateCommandFlags('node', ['--require', 'malicious-module'])
|
||||
}).toThrow("Argument '--require' is not allowed for command 'node'")
|
||||
})
|
||||
|
||||
it('should block --loader/--experimental-loader flags', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('node', ['--loader', './malicious-loader.mjs'])
|
||||
}).toThrow("Argument '--loader' is not allowed for command 'node'")
|
||||
|
||||
expect(() => {
|
||||
validateCommandFlags('node', ['--experimental-loader', './malicious-loader.mjs'])
|
||||
}).toThrow("Argument '--experimental-loader' is not allowed for command 'node'")
|
||||
})
|
||||
|
||||
it('should block --import flag', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('node', ['--import', './malicious.mjs'])
|
||||
}).toThrow("Argument '--import' is not allowed for command 'node'")
|
||||
})
|
||||
|
||||
it('should block --env-file flag', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('node', ['--env-file', '.env'])
|
||||
}).toThrow("Argument '--env-file' is not allowed for command 'node'")
|
||||
|
||||
expect(() => {
|
||||
validateCommandFlags('node', ['--env-file=.env'])
|
||||
}).toThrow("contains flag '--env-file'")
|
||||
})
|
||||
|
||||
it('should allow legitimate node usage', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('node', ['server.js'])
|
||||
@@ -189,6 +241,56 @@ describe('MCP Security Validations', () => {
|
||||
}).toThrow("Argument '--ipc' is not allowed for command 'docker'")
|
||||
})
|
||||
|
||||
it('should block --mount flag', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('docker', ['--mount', 'type=bind,source=/,target=/host'])
|
||||
}).toThrow("Argument '--mount' is not allowed for command 'docker'")
|
||||
|
||||
expect(() => {
|
||||
validateCommandFlags('docker', ['--mount=type=bind,source=/,target=/host'])
|
||||
}).toThrow("contains flag '--mount'")
|
||||
})
|
||||
|
||||
it('should block --device flag', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('docker', ['--device', '/dev/sda'])
|
||||
}).toThrow("Argument '--device' is not allowed for command 'docker'")
|
||||
})
|
||||
|
||||
it('should block --entrypoint flag', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('docker', ['--entrypoint', '/bin/sh'])
|
||||
}).toThrow("Argument '--entrypoint' is not allowed for command 'docker'")
|
||||
})
|
||||
|
||||
it('should block compose subcommand', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('docker', ['compose', 'up'])
|
||||
}).toThrow("Argument 'compose' is not allowed for command 'docker'")
|
||||
})
|
||||
|
||||
it('should block --volumes-from flag', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('docker', ['--volumes-from', 'other-container'])
|
||||
}).toThrow("Argument '--volumes-from' is not allowed for command 'docker'")
|
||||
})
|
||||
|
||||
it('should block --env-file flag', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('docker', ['--env-file', '/etc/secrets'])
|
||||
}).toThrow("Argument '--env-file' is not allowed for command 'docker'")
|
||||
|
||||
expect(() => {
|
||||
validateCommandFlags('docker', ['--env-file=/etc/secrets'])
|
||||
}).toThrow("contains flag '--env-file'")
|
||||
})
|
||||
|
||||
it('should block build subcommand', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('docker', ['build', 'https://evil.com/'])
|
||||
}).toThrow("Argument 'build' is not allowed for command 'docker'")
|
||||
})
|
||||
|
||||
it('should allow safe docker usage', () => {
|
||||
expect(() => {
|
||||
validateCommandFlags('docker', ['ps'])
|
||||
@@ -271,6 +373,12 @@ describe('MCP Security Validations', () => {
|
||||
}).toThrow('Argument contains potential local file access')
|
||||
})
|
||||
|
||||
it('should block double-slash absolute paths', () => {
|
||||
expect(() => {
|
||||
validateArgsForLocalFileAccess(['//etc/passwd'])
|
||||
}).toThrow('Argument contains potential local file access')
|
||||
})
|
||||
|
||||
it('should block path traversal', () => {
|
||||
expect(() => {
|
||||
validateArgsForLocalFileAccess(['../../../etc/passwd'])
|
||||
|
||||
@@ -190,7 +190,7 @@ function createSchemaModel(
|
||||
export const validateArgsForLocalFileAccess = (args: string[]): void => {
|
||||
const dangerousPatterns = [
|
||||
// Absolute paths
|
||||
/^\/[^/]/, // Unix absolute paths starting with /
|
||||
/^\//, // Unix absolute paths starting with /
|
||||
/^[a-zA-Z]:\\/, // Windows absolute paths like C:\
|
||||
|
||||
// Relative paths that could escape current directory
|
||||
@@ -286,7 +286,9 @@ export const validateCommandFlags = (command: string, args: string[]): void => {
|
||||
'-c', // Execute shell commands
|
||||
'--call', // Execute shell commands
|
||||
'--shell-auto-fallback', // Shell execution fallback
|
||||
'-y' // Auto-confirms installation prompts
|
||||
'-y', // Auto-confirms installation prompts
|
||||
'--yes', // Auto-confirms installation prompts
|
||||
'--node-options' // Passes arbitrary Node flags to underlying process, bypassing node flag blocklist
|
||||
],
|
||||
node: [
|
||||
'-e', // Execute JavaScript code
|
||||
@@ -295,7 +297,13 @@ export const validateCommandFlags = (command: string, args: string[]): void => {
|
||||
'--print', // Evaluate and print JavaScript code
|
||||
'--inspect', // Enable remote debugging (security risk)
|
||||
'--inspect-brk', // Enable remote debugging with breakpoint (security risk)
|
||||
'--experimental-policy' // Could load malicious policies
|
||||
'--experimental-policy', // Could load malicious policies
|
||||
'-r', // Short alias for --require
|
||||
'--require', // Preload a CommonJS module before script runs
|
||||
'--loader', // Custom ES module loader hook (code execution)
|
||||
'--experimental-loader', // Same as --loader, older Node alias
|
||||
'--import', // Preload ESM module before entry script (Node 18+)
|
||||
'--env-file' // Read env vars from a local file (Node 20+, local file access)
|
||||
],
|
||||
python: [
|
||||
'-c', // Execute Python code
|
||||
@@ -307,15 +315,22 @@ export const validateCommandFlags = (command: string, args: string[]): void => {
|
||||
],
|
||||
docker: [
|
||||
'run', // Run containers (too powerful)
|
||||
'build', // Pulls a container and executes the run instructions
|
||||
'exec', // Execute in containers
|
||||
'compose', // Subcommand that starts containers (same risk as run)
|
||||
'-v', // Mount host filesystems
|
||||
'--volume', // Mount host filesystems
|
||||
'--mount', // Alternative to -v/--volume for mounting host paths
|
||||
'--volumes-from', // Mount volumes from another container (filesystem access)
|
||||
'--privileged', // Privileged mode
|
||||
'--cap-add', // Add capabilities
|
||||
'--security-opt', // Modify security options
|
||||
'--device', // Add host device files to container (privilege escalation)
|
||||
'--entrypoint', // Override container entrypoint (arbitrary code execution)
|
||||
'--network', // Host network access (catches --network=host and --network host)
|
||||
'--pid', // Host PID namespace (catches --pid=host and --pid host)
|
||||
'--ipc' // Host IPC namespace (catches --ipc=host and --ipc host)
|
||||
'--ipc', // Host IPC namespace (catches --ipc=host and --ipc host)
|
||||
'--env-file' // Read env vars from a local host file (local file access)
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user