MCPcopy Index your code
hub / github.com/codeaashu/claude-code / hasShellQuoteSingleQuoteBug

Function hasShellQuoteSingleQuoteBug

src/utils/bash/shellQuote.ts:190–265  ·  view source on GitHub ↗
(command: string)

Source from the content-addressed store, hash-verified

188 * because shell-quote thinks it's all one single-quoted string.
189 */
190export function hasShellQuoteSingleQuoteBug(command: string): boolean {
191 // Walk the command with correct bash single-quote semantics
192 let inSingleQuote = false
193 let inDoubleQuote = false
194
195 for (let i = 0; i < command.length; i++) {
196 const char = command[i]
197
198 // Handle backslash escaping outside of single quotes
199 if (char === '\\' && !inSingleQuote) {
200 // Skip the next character (it's escaped)
201 i++
202 continue
203 }
204
205 if (char === '"' && !inSingleQuote) {
206 inDoubleQuote = !inDoubleQuote
207 continue
208 }
209
210 if (char === "'" && !inDoubleQuote) {
211 inSingleQuote = !inSingleQuote
212
213 // Check if we just closed a single quote and the content ends with
214 // trailing backslashes. shell-quote's chunker regex '((\\'|[^'])*?)'
215 // incorrectly treats \' as an escape sequence inside single quotes,
216 // while bash treats backslash as literal. This creates a differential
217 // where shell-quote merges tokens that bash treats as separate.
218 //
219 // Odd trailing \'s = always a bug:
220 // '\' -> shell-quote: \' = literal ', still open. bash: \, closed.
221 // 'abc\' -> shell-quote: abc then \' = literal ', still open. bash: abc\, closed.
222 // '\\\' -> shell-quote: \\ + \', still open. bash: \\\, closed.
223 //
224 // Even trailing \'s = bug ONLY when a later ' exists in the command:
225 // '\\' alone -> shell-quote backtracks, both parsers agree string closes. OK.
226 // '\\' 'next' -> shell-quote: \' consumes the closing ', finds next ' as
227 // false close, merges tokens. bash: two separate tokens.
228 //
229 // Detail: the regex alternation tries \' before [^']. For '\\', it matches
230 // the first \ via [^'] (next char is \, not '), then the second \ via \'
231 // (next char IS '). This consumes the closing '. The regex continues reading
232 // until it finds another ' to close the match. If none exists, it backtracks
233 // to [^'] for the second \ and closes correctly. If a later ' exists (e.g.,
234 // the opener of the next single-quoted arg), no backtracking occurs and
235 // tokens merge. See H1 report: git ls-remote 'safe\\' '--upload-pack=evil' 'repo'
236 // shell-quote: ["git","ls-remote","safe\\\\ --upload-pack=evil repo"]
237 // bash: ["git","ls-remote","safe\\\\","--upload-pack=evil","repo"]
238 if (!inSingleQuote) {
239 let backslashCount = 0
240 let j = i - 1
241 while (j >= 0 && command[j] === '\\') {
242 backslashCount++
243 j--
244 }
245 if (backslashCount > 0 && backslashCount % 2 === 1) {
246 return true
247 }

Callers 3

rearrangePipeCommandFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected