TLDR: I escaped the message body in my AppleScript iMessage bridge. I didn't escape the recipient handle. They're both interpolated into the same string. Same escaping. Two seconds to fix. One full year to get caught.
The Setup
Apollo (my local AI assistant) has an iMessage bridge.
It works like this: Apollo drafts a message — recipient handle plus body — and writes it to a JSON file. A second step fires the draft via osascript, building an AppleScript string and passing it to Messages.app.
The fire step looks roughly like this:
escaped = body.replace("\\", "\\\\").replace('"', '\\"')
send_string = '"' + escaped.replace("\n", '" & linefeed & "') + '"'
apple_script = f'''tell application "Messages"
set targetBuddy to "{handle}"
set theBuddy to participant targetBuddy of targetService
send {send_string} to theBuddy
end tell'''
See the problem?
The Bug
The body is escaped. Backslash first, then double-quote — correct order, correctly done.
The handle goes in raw.
Both of them are interpolated into the same AppleScript string. Both of them are surrounded by double-quotes in the script. If handle contains a ", it breaks out of the string — and whatever comes after it runs as AppleScript.
A crafted handle like:
+1234" & (do shell script "open /Applications/Calculator.app") & "
…executes. That's arbitrary code on my machine.
How It Got Found
Not a live exploit. Not something that blew up in my face.
Found by Apollo's daily security audit pass — on 2026-06-10, Finding 4 in that day's run.
Which is actually the honest part of this story: I already knew body needed escaping. I'd thought about it, done it correctly. Then I forgot to think about the other value in the exact same template.
The asymmetry is the tell. Whenever you sanitize one variable in a string template, you've already acknowledged the template is dangerous. That's the moment to check every other variable in it.
I didn't. Apollo's daily security audit pass did.
The Fix
Two lines. Exactly identical to the body escaping:
handle_escaped = handle.replace("\\", "\\\\").replace('"', '\\"')
Then use handle_escaped in the AppleScript. Done.
The commit comment spells out why the handle is untrusted even though it's my assistant writing it: Apollo stages drafts from emails and transcripts it's summarizing — untrusted external content. A poisoned email subject could work a handle into the draft. Trust boundaries erode fast when an AI is the middle layer.
Why This Matters
This is the most common flavor of injection bug I know: partial sanitization. You sanitize the thing you were thinking about. You don't sanitize the other thing in the same slot.
SQL injection, shell injection, AppleScript injection — the pattern is the same. One variable got the treatment. Another didn't.
The rule I'm taking from this: every time you escape something in a string template, stop and read the whole template. Every %s, every f-string {var}, every concatenated piece. If one variable needs escaping, assume they all do until you've confirmed otherwise.
The audit found it. Next time I want to find it myself first.