From 3259071f7eeba4fe8b214c01c49c0aae0f04fb77 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Mon, 9 Feb 2026 08:01:26 -0800 Subject: [PATCH] Skip splitting on escaped semicolons in splitCommands A backslash-escaped semicolon (\;) outside quotes is a literal character in shell syntax, not a command separator. Reuse the existing isEscaped() helper to check delimiter parity. Co-Authored-By: Claude Opus 4.6 --- plugins/importer-curl/src/index.ts | 4 ++-- plugins/importer-curl/tests/index.test.ts | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/plugins/importer-curl/src/index.ts b/plugins/importer-curl/src/index.ts index 5a489fa1..23542c1e 100644 --- a/plugins/importer-curl/src/index.ts +++ b/plugins/importer-curl/src/index.ts @@ -120,8 +120,8 @@ function splitCommands(rawData: string): string[] { const inQuote = inSingleQuote || inDoubleQuote || inDollarQuote; - // Split on ;, newline, or CRLF when not inside quotes - if (!inQuote && (ch === ';' || ch === '\n' || (ch === '\r' && next === '\n'))) { + // Split on ;, newline, or CRLF when not inside quotes and not escaped + if (!inQuote && !isEscaped(i) && (ch === ';' || ch === '\n' || (ch === '\r' && next === '\n'))) { if (ch === '\r') i++; // Skip the \n in \r\n if (current.trim()) { commands.push(current.trim()); diff --git a/plugins/importer-curl/tests/index.test.ts b/plugins/importer-curl/tests/index.test.ts index df7e712f..3c986817 100644 --- a/plugins/importer-curl/tests/index.test.ts +++ b/plugins/importer-curl/tests/index.test.ts @@ -599,6 +599,26 @@ describe('importer-curl', () => { }); }); + test('Does not split on escaped semicolon outside quotes', () => { + // In shell, \; is a literal semicolon and should not split commands. + // This should be treated as a single curl command with the URL "https://yaak.app?a=1;b=2" + expect( + convertCurl('curl https://yaak.app?a=1\\;b=2'), + ).toEqual({ + resources: { + workspaces: [baseWorkspace()], + httpRequests: [ + baseRequest({ + url: 'https://yaak.app', + urlParameters: [ + { name: 'a', value: '1;b=2', enabled: true }, + ], + }), + ], + }, + }); + }); + test('Imports multipart form data with text-only fields from --data-raw', () => { const curlCommand = `curl 'http://example.com/api' \ -H 'Content-Type: multipart/form-data; boundary=----FormBoundary123' \