diff --git a/packages/core/src/utils/shell-utils.test.ts b/packages/core/src/utils/shell-utils.test.ts index b95e95c7b..f03814268 100644 --- a/packages/core/src/utils/shell-utils.test.ts +++ b/packages/core/src/utils/shell-utils.test.ts @@ -442,6 +442,18 @@ describe('getCommandRoots', () => { expect(result).toEqual(['grep']); }); + it('should treat escaped newlines in chained commands as line continuations', async () => { + const result = getCommandRoots( + 'cd project && \\\ngit add file.php && \\\ngit commit -m "feat"', + ); + expect(result).toEqual(['cd', 'git', 'git']); + }); + + it('should not treat escaped CRLF as a line continuation', async () => { + const result = getCommandRoots('echo SAFE \\\r\nrm -rf /'); + expect(result).toEqual(['echo', 'rm']); + }); + it('should filter out empty segments from consecutive newlines', async () => { const result = getCommandRoots('ls\n\ngrep foo'); expect(result).toEqual(['ls', 'grep']); diff --git a/packages/core/src/utils/shell-utils.ts b/packages/core/src/utils/shell-utils.ts index ac4a2d0d5..55d778dde 100644 --- a/packages/core/src/utils/shell-utils.ts +++ b/packages/core/src/utils/shell-utils.ts @@ -224,6 +224,11 @@ export function splitCommands(command: string): string[] { const char = command[i]; const nextChar = command[i + 1]; + if (!inSingleQuotes && char === '\\' && nextChar === '\n') { + i += 2; + continue; + } + if (char === '\\' && i < command.length - 1) { currentCommand += char + command[i + 1]; i += 2;