Skip to content

Commit 18e5cfd

Browse files
committed
add kilocode change markers
1 parent c4ad884 commit 18e5cfd

File tree

2 files changed

+18
-0
lines changed

2 files changed

+18
-0
lines changed

webview-ui/src/utils/__tests__/command-validation.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ import {
1212
CommandValidator,
1313
createCommandValidator,
1414
containsDangerousSubstitution,
15+
// kilocode_change start
1516
protectNewlinesInQuotes,
1617
NEWLINE_PLACEHOLDER,
1718
CARRIAGE_RETURN_PLACEHOLDER,
19+
// kilocode_change end
1820
} from "../command-validation"
1921

22+
// kilocode_change start
2023
describe("protectNewlinesInQuotes", () => {
2124
const newlinePlaceholder = NEWLINE_PLACEHOLDER
2225
const crPlaceholder = CARRIAGE_RETURN_PLACEHOLDER
@@ -135,6 +138,7 @@ describe("protectNewlinesInQuotes", () => {
135138
})
136139
})
137140
})
141+
// kilocode_change end
138142

139143
describe("Command Validation", () => {
140144
describe("parseCommand", () => {
@@ -232,6 +236,7 @@ describe("Command Validation", () => {
232236
])
233237
})
234238

239+
// kilocode_change start allowed newlines within quotes
235240
it("preserves newlines within quotes", () => {
236241
// Newlines inside quoted strings should be preserved as part of the command
237242
// Using template literal to create actual newline
@@ -241,6 +246,7 @@ git status`
241246
// The newlines inside quotes are preserved, so we get two commands
242247
expect(parseCommand(commandWithNewlineInQuotes)).toEqual(['echo "Hello\nWorld"', "git status"])
243248
})
249+
// kilocode_change end
244250

245251
it("handles quoted strings on single line", () => {
246252
// When quotes are on the same line, they are preserved
@@ -1204,6 +1210,7 @@ describe("Unified Command Decision Functions", () => {
12041210
expect(getCommandDecision("dangerous", allowed, denied)).toBe("ask_user")
12051211
expect(getCommandDecision("npm install && dangerous", allowed, denied)).toBe("ask_user")
12061212
})
1213+
// kilocode_change start
12071214
// Real-world regression: multi-line git commit message in quotes should be treated as a single command
12081215
describe("real-world: multi-line git commit message", () => {
12091216
it("auto-approves when commit message is single-line", () => {
@@ -1240,6 +1247,7 @@ describe("Unified Command Decision Functions", () => {
12401247
expect(parsed[0]).toContain("- point b")
12411248
})
12421249
})
1250+
// kilocode_change end
12431251
})
12441252

12451253
describe("CommandValidator Integration Tests", () => {

webview-ui/src/utils/command-validation.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { parse } from "shell-quote"
22

33
type ShellToken = string | { op: string } | { command: string }
44

5+
// kilocode_change start
56
/**
67
* Placeholders used to protect newlines within quoted strings during command parsing.
78
* These constants are used by the protectNewlinesInQuotes function to temporarily replace
@@ -10,6 +11,7 @@ type ShellToken = string | { op: string } | { command: string }
1011
*/
1112
export const NEWLINE_PLACEHOLDER = "___NEWLINE___"
1213
export const CARRIAGE_RETURN_PLACEHOLDER = "___CARRIAGE_RETURN___"
14+
// kilocode_change end
1315

1416
/**
1517
* # Command Denylist Feature - Longest Prefix Match Strategy
@@ -131,6 +133,7 @@ export function containsDangerousSubstitution(source: string): boolean {
131133
)
132134
}
133135

136+
// kilocode_change start
134137
/**
135138
* Protect newlines inside quoted strings by replacing them with placeholders.
136139
* This handles proper shell quoting rules where quotes can be concatenated.
@@ -223,7 +226,9 @@ export function protectNewlinesInQuotes(
223226

224227
return result
225228
}
229+
// kilocode_change end
226230

231+
// kilocode_change start added exception for quoted newlines
227232
/**
228233
* Split a command string into individual sub-commands by
229234
* chaining operators (&&, ||, ;, |, or &) and newlines.
@@ -235,16 +240,19 @@ export function protectNewlinesInQuotes(
235240
* - Chain operators (&&, ||, ;, |, &)
236241
* - Newlines as command separators (but not within quotes)
237242
*/
243+
//kilocode_change end
238244
export function parseCommand(command: string): string[] {
239245
if (!command?.trim()) return []
240246

247+
// kilocode_change start
241248
// First, protect newlines inside quoted strings by replacing them with placeholders
242249
// This prevents splitting multi-line quoted strings (e.g., git commit -m "multi\nline")
243250
const protectedCommand = protectNewlinesInQuotes(command, NEWLINE_PLACEHOLDER, CARRIAGE_RETURN_PLACEHOLDER)
244251

245252
// Split by newlines (handle different line ending formats)
246253
// This regex splits on \r\n (Windows), \n (Unix), or \r (old Mac)
247254
const lines = protectedCommand.split(/\r\n|\r|\n/)
255+
// kilocode_change end
248256
const allCommands: string[] = []
249257

250258
for (const line of lines) {
@@ -256,12 +264,14 @@ export function parseCommand(command: string): string[] {
256264
allCommands.push(...lineCommands)
257265
}
258266

267+
// kilocode_change start
259268
// Restore newlines and carriage returns in quoted strings
260269
return allCommands.map((cmd) =>
261270
cmd
262271
.replace(new RegExp(NEWLINE_PLACEHOLDER, "g"), "\n")
263272
.replace(new RegExp(CARRIAGE_RETURN_PLACEHOLDER, "g"), "\r"),
264273
)
274+
// kilocode_change end
265275
}
266276

267277
/**

0 commit comments

Comments
 (0)