TL;DR: A Swift app that builds AppleScript around user-controlled paths can cross a data-code boundary and permit arbitrary command execution when escaping rules do not match the target interpreter, according to Sonar. The case reinforces that native argument passing is safer than string-built scripts, especially where untrusted content can arrive through files, archives, or repositories.
At a glance
What this is: This is a Sonar analysis of an AppleScript injection flaw in OpenInTerminal that could let a crafted folder path trigger arbitrary code execution on macOS.
Why it matters: It matters because many enterprise workflows still trust local files, archives, and developer tooling paths as low-risk inputs, yet those inputs can become execution vectors without any identity or privilege change visible to standard IAM controls.
👉 Read Sonar's analysis of the OpenInTerminal AppleScript injection flaw
Context
AppleScript injection is a code execution problem, not just a bad input-handling bug. The issue appears when an application builds a command string for one interpreter and then passes it into another interpreter with different escaping rules. In this case, a folder path that looks harmless to a user can break out of the intended string context and become executable AppleScript, which is why AppleScript injection matters to endpoint and developer security teams.
The identity angle is indirect but real: local attacks often start from untrusted content received through repositories, ZIP archives, shared folders, or developer workflows, where the system trusts the file path rather than an authenticated user action. That means standard access governance does not stop the exploit path, and application design becomes the real control boundary. This starting position is common in macOS utility tooling and developer-facing desktop apps.
For identity and access teams, the lesson is broader than macOS. When software treats user-controlled paths, tokens, or metadata as executable instructions, the safe boundary is no longer authentication but argument handling, process isolation, and least-privilege execution.
Key questions
Q: How should security teams prevent AppleScript injection in macOS utilities?
A: Use native APIs that preserve argument boundaries, and avoid building AppleScript or shell commands from user-controlled paths. If scripting is unavoidable, validate inputs before they cross an interpreter boundary and test with quotes, comments, nested folders, and symlinks. The safest pattern is to make data stay data all the way to execution.
Q: Why do file paths become dangerous in command execution flows?
A: A file path becomes dangerous when software treats it as part of a command string instead of a literal parameter. At that point, quote characters, separators, and comment syntax can change program behaviour. The risk is highest in applications that chain multiple interpreters, because each one may parse the same input differently.
Q: What do developers get wrong about escaping input for scripts?
A: They often escape input for the first interpreter they think about, then reuse it in a second interpreter with different rules. That creates a false sense of safety. Escaping is not a substitute for structure, and once data has to survive multiple parsers, the chance of a boundary break rises quickly.
Q: What should teams do when a utility shells out through another language?
A: Inventory every place the application shells out through another language, then decide whether the feature can be rewritten to use a direct process call. If it cannot, apply strict input validation, reduce user control over command parameters, and test the full path from file system input to execution output.
Technical breakdown
Why AppleScript injection happens in path handling
AppleScript injection occurs when untrusted data is inserted into an AppleScript command string instead of being passed as a structured argument. The vulnerability usually emerges when developers try to escape characters for the wrong interpreter, then reuse that output inside another execution context. In OpenInTerminal, a file system path was escaped for a shell command but still remained dangerous to the outer AppleScript parser, which could then interpret quote characters, comments, and concatenation as code. Practical implication: treat file paths and similar metadata as untrusted input all the way to process execution.
Practical implication: Use structured argument passing, not string concatenation, for any command that crosses an interpreter boundary.
How attackers chain folder names into code execution
Exploit construction depends on turning path segments into script fragments that survive escaping, line breaks, and length limits. Attackers can encode payload characters as ASCII values, split commands across nested directories, and use comment syntax to hide path separators or terminate trailing syntax safely. Symlinks can then collapse the visible path so the victim only sees a plausible folder structure. This is a classic data-to-code boundary failure: each layer appears to sanitise input, but the sanitisation is not aligned with the final parser. Practical implication: if a payload can be assembled from filenames, the application has already lost the trust boundary.
Practical implication: Block execution from user-derived paths and test parser interactions with chained, multi-layer inputs.
Why native process execution closes the gap
Native process APIs preserve argument boundaries, which means the operating system receives a command and its parameters separately rather than as one executable string. That is materially safer than building an interpreted script, because the runtime does not need to guess where data ends and code begins. The fix described in the article replaces the dynamic AppleScript shell command with structured argument passing and POSIX quoting at the final boundary. This pattern mirrors subprocess execution with shell disabled. Practical implication: choose APIs that do not require sanitising a command string in the first place.
Practical implication: Replace interpreted command strings with APIs that pass each argument separately and preserve literal values.
Threat narrative
Attacker objective: The attacker wants arbitrary code execution on the victim's macOS device through a trusted local utility.
- Entry begins when the victim receives or clones a malicious folder structure, often hidden inside a repository, archive, or symlinked directory tree.
- Escalation occurs when the application converts the folder path into AppleScript that can be broken out of with crafted characters, allowing the attacker to inject commands.
- Impact follows when the injected script executes arbitrary code on the victim's macOS system, such as launching Calculator or any other payload the attacker encodes.
NHI Mgmt Group analysis
AppleScript injection is a boundary-management failure, not a syntax mistake. The issue in OpenInTerminal is not that one quote was escaped incorrectly, but that one execution context tried to compensate for another. When applications compose code across Swift, AppleScript, and the shell, the control failure is mismatched trust boundaries, not only input filtering. Practitioners should treat any multi-interpreter chain as a code execution surface, not a convenience layer.
Path-based execution deserves the same governance attention as secrets handling. A folder name, archive payload, or repository path can carry as much operational risk as a token if the application later interprets it. That is the same governance logic behind workload identity and NHI security: data that looks inert can become executable authority when the runtime treats it as instruction. The practical conclusion is to govern execution pathways, not just credentials.
Argument boundaries are the real named concept here. When developers preserve literal arguments instead of building command strings, they eliminate an entire class of injection risk. This is directly aligned with secure coding guidance in NIST SP 800-53 and the broader principle of separating code from data. For teams, the takeaway is to review any desktop utility, CLI wrapper, or automation that shells out through a secondary interpreter.
Desktop utilities now sit inside the same attack surface as developer tooling and automation. A benign file-handling feature can become an execution primitive when it accepts untrusted paths from archives, synced folders, or git clones. That makes endpoint hardening, software review, and secure SDLC controls relevant even for small utilities that do not look like security products. Security teams should include these apps in their application risk inventory, not just their vulnerability scanner backlog.
What this signals
AppleScript injection is a reminder that application security and identity governance now overlap wherever untrusted inputs can trigger execution. The control question is not only who is authenticated, but whether a local process can convert a file, path, or archive into executable authority without a reviewable security boundary.
NHI programmes should pay attention because the same design mistake appears in machine identity systems that concatenate tokens, commands, or metadata instead of preserving structure. For a related control lens, the OWASP NHI Top 10 and NIST SP 800-53 Rev 5 Security and Privacy Controls both reinforce separation between data handling and privileged execution.
As desktop tools, developer utilities, and automation layers continue to converge, teams need to treat path handling and command invocation as governed code paths. That means reviewing software inventory for hidden interpreter chains and pairing secure coding checks with endpoint execution controls.
For practitioners
- Eliminate interpreted command strings Replace any do shell script style pattern with native process execution or separately bound arguments so untrusted path data never becomes code.
- Audit secondary interpreter chains Review desktop utilities, automation scripts, and developer tools that pass Swift, Python, JavaScript, AppleScript, or shell output into another runtime.
- Test with nested and symlinked inputs Build malicious-path test cases that include nested folders, symlinks, quotes, tabs, and archive extraction flows to see where escaping breaks.
- Treat file paths as untrusted execution input Classify user-supplied paths, repository content, and archive names as security-sensitive inputs in your SDLC and code review checklist.
Key takeaways
- The OpenInTerminal issue shows how a harmless-looking folder path can become executable code when one interpreter's escaping rules are reused in another.
- The root problem is boundary failure across Swift, AppleScript, and shell execution, not simply a missing escape character.
- Teams should replace string-built commands with native process execution and test any multi-interpreter flow with malicious nested paths, symlinks, and archive inputs.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
MITRE ATT&CK address the attack and risk surface, while NIST CSF 2.0, NIST SP 800-53 Rev 5 and CIS Controls v8 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| MITRE ATT&CK | TA0002 , Execution; TA0006 , Credential Access | The article centres on malicious code execution through a user-controlled input boundary. |
| NIST CSF 2.0 | PR.AC-3 | The flaw arises where trust is assigned to file paths without adequate control validation. |
| NIST SP 800-53 Rev 5 | SI-10 | The issue is a classic input validation failure crossing a parser boundary. |
| CIS Controls v8 | CIS-16 , Application Software Security | The vulnerability sits in application code and secure development practice. |
Map interpreter-boundary failures to execution techniques and block any command path that accepts untrusted strings.
Key terms
- AppleScript Injection: AppleScript injection happens when untrusted input is inserted into an AppleScript command so the interpreter treats data as code. The flaw usually appears when applications build script strings dynamically instead of passing structured arguments, allowing quotes, comments, and concatenation to change execution behaviour.
- Data-Code Boundary: A data-code boundary is the point where user input stops being treated as content and starts being interpreted as instructions. Security failures happen when that boundary is unclear or inconsistent across layers, especially when one runtime generates code for another runtime to execute.
- Secondary Interpreter Chain: A secondary interpreter chain is a sequence where one language or runtime hands output to another, such as Swift to AppleScript to shell. Each step can reinterpret the same string differently, which multiplies the risk of injection unless the application preserves argument boundaries end to end.
What's in the full article
Sonar's full blog post covers the technical exploit details this post intentionally leaves for the source:
- The exact AppleScript payload construction used to break out of the string context and reach arbitrary command execution
- A step-by-step explanation of how nested folders and symlinks reduce the amount of user interaction needed
- The before-and-after code path showing how structured arguments replaced string-built shell commands in the fix
- The disclosure timeline and remediation notes for the affected OpenInTerminal versions
👉 Sonar's full post covers the exploit chain, escaping failure, and the fix in v2.3.9
Deepen your knowledge
NHI Foundation Level course, the industry's only accredited NHI security programme, covers NHI governance, secrets management, and machine identity security. It helps practitioners connect identity controls to the broader execution risks their programmes must manage.
Published by the NHIMG editorial team on August 18, 2026.
NHI Mgmt Group — the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org