fix: use double-quoted Spotlight query for mdfind app names#7464
Conversation
Process.arguments bypasses the shell, so the shell-style single-quote
escaping ('\'') was passed raw to mdfind, breaking Spotlight query
parsing. Switch to double-quoted query values with proper double-quote
escaping instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| // double quotes. Process.arguments bypasses the shell, so shell-style | ||
| // single-quote escaping (e.g. '\'') would be passed raw to mdfind and | ||
| // break Spotlight query parsing. | ||
| let sanitizedName = name.replacingOccurrences(of: "\"", with: "\\\"") |
There was a problem hiding this comment.
🟡 Missing backslash escaping in mdfind query allows malformed Spotlight queries
The sanitization on line 388 only escapes double quotes but not backslashes. Since mdfind's Spotlight query parser treats \ as an escape character inside double-quoted strings, an app name containing a backslash will produce a malformed query.
Root Cause and Example
If name is foo\ (contains a literal backslash), the sanitized name is still foo\ (no replacement occurs), and the query becomes:
kMDItemKind == 'Application' && kMDItemDisplayName == "foo\"
Here \" is interpreted by mdfind as an escaped double quote, so the string literal is never terminated and the query is malformed. This causes mdfind to fail (exit non-zero), and the function returns nil.
More critically, a name like foo\"bar would have its " escaped to \", producing foo\\\"bar in the query — but the original backslash isn't escaped, so mdfind sees foo\"bar where \" is an escaped quote, breaking the intended string boundary.
Backslashes must be escaped before double quotes to ensure correct nesting:
let sanitizedName = name
.replacingOccurrences(of: "\\", with: "\\\\")
.replacingOccurrences(of: "\"", with: "\\\"")Impact: While app names with backslashes are extremely rare on macOS, this is an incomplete fix for the escaping problem the PR is trying to solve. The function degrades gracefully (returns nil), so the impact is limited to a failed lookup rather than a crash.
| let sanitizedName = name.replacingOccurrences(of: "\"", with: "\\\"") | |
| let sanitizedName = name.replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences(of: "\"", with: "\\\"") |
Was this helpful? React with 👍 or 👎 to provide feedback.
Addresses review feedback on PR #7464: the sanitization only escaped double quotes but not backslashes. Since Spotlight's query parser treats `\` as an escape character inside double-quoted strings, an app name containing a backslash would produce a malformed query. Escape backslashes before double quotes to ensure correct nesting. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Addresses review feedback on PR #7464: the sanitization only escaped double quotes but not backslashes. Since Spotlight's query parser treats `\` as an escape character inside double-quoted strings, an app name containing a backslash would produce a malformed query. Escape backslashes before double quotes to ensure correct nesting. Co-authored-by: Vellum Assistant <assistant@vellum.ai> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Switches mdfind query value from single-quoted with shell-style escaping to double-quoted with proper escaping, since Process.arguments bypasses the shell. Addresses feedback from #7456.
Summary
Process.argumentspasses arguments directly to the executable without shell interpretation, so the POSIX shell idiom'\''for escaping single quotes was being passed raw tomdfind, breaking Spotlight query parsing.kMDItemDisplayNamecomparison value to use double quotes with proper double-quote escaping instead.Test plan
./build.shmdfindfor apps with standard names (e.g., "Safari", "Terminal")🤖 Generated with Claude Code