从间接提示注入到 macOS Terminal 的 DNS 数据外泄
From Indirect Prompt Injection to DNS Exfiltration in macOS Terminal · Embrace The Red
Johann Rehberger 披露其 Terminal DiLLMa 后续研究:macOS Terminal 曾允许特定 ANSI 转义码序列发起 DNS 请求,攻击者可借间接提示注入让 LLM CLI 工具读取表格数据并以 DNS 请求外泄。该问题已于 2025 年 11 月 3 日发布的 macOS Tahoe 26.1 中修复,作者获致谢。作者指出 LLM 集成的 CLI 应用常未处理 ANSI 转义字符,建议默认用类似 cat -v 的方式编码控制字符,并提供了 Python 与 Go 的编码函数。
正文
当前显示原文,中文全文译文尚未就绪。
This is a follow-up to my previous Terminal DiLLMa research, and there is a positive outcome: Apple fixed a macOS Terminal behavior that enabled a DNS-based data exfiltration technique.
David Leadbeater originally discovered an interesting behavior in the macOS Terminal app that allowed a special sequence of ANSI escape codes to issue DNS requests.
In short, this triggered a DNS request from the macOS Terminal app:
Interestingly, it had still not been fixed when I looked into it.
I learned about this behavior when watching STÖK’s presentation at Ekoparty in 2024, where he talked about injecting ANSI Escape Codes into log files. It’s a great talk, I recommend watching it.
How could this be meaningfully exploited? LLMs and Agents!
Rendering ANSI Escape Codes with AI Agents!
Leon Derczynski discovered that LLMs can emit ANSI escape codes, e.g. the ESC (ASCII 27).
When I saw that, it seemed like a great way to hijack AI agents and LLM CLI tools running on the command line and to exfiltrate data.
Proof-of-Concept Exploit
Here is a demo that shows the issue with a typical CLI app:
We create a DNS listener. I like Project Discovery tools, and they have interactsh-client:; Next, the scenario involves the user analyzing a spreadsheet with an LLM-integrated CLI app using the macOS Terminal App. For the demo, I created my own dillma.py tool, but there are many such AI tools and coding agents out there!
The spreadsheet contains a malicious feedback cell that tells the AI to retrieve the names of the previous three rows and place them into a string to render to the terminal. This is the exact feedback string:
Interestingly, BEL is ASCII 7, not 10. That was my mistake in the prompt, but it did not prevent the in-context learning instruction from working.
As a result, the AI tool is hijacked, reads data from other rows in the spreadsheet and emits ANSI escape codes. The Terminal app interprets the sequence and issues DNS requests containing the stolen data, in this POC demo a few names of other users in the spreadsheet
Pretty wild.
Video Walkthrough
Here is an end-to-end demo showing this in action:
I recorded the video in December 2024, when I first got the end-to-end attack working, and subsequently shared it with Apple.
Disclosure
I reported this to Apple in December 2024; Apple addressed the issue in macOS Tahoe 26.1, released on November 3, 2025. After installing the update, the same escape sequence no longer triggers a DNS request in the Terminal app; Tahoe 26.1 release notes
Pretty cool. I even got credited in the release notes. 🙌
Although Apple mitigated the DNS exfiltration vector, it’s important to highlight that LLM-integrated CLI applications often do not handle ANSI escape characters well and pass them directly to the terminal. Depending on the capabilities of the terminal emulator, this can result in other unwanted behavior.
CLI tools should safely encode control characters by default, using an approach similar to cat -v. Raw terminal output should require explicit opt-in.
For my own projects, I created two functions a while ago for Python and Go code. They encode output to a form of caret notation, so that bad data can’t hijack the terminal:
Python Version; Go Version
Feel free to use, adjust as you see fit. No warranty or liability.
Conclusion
This post was a follow up on the Terminal DiLLMa research, and how we got a behavior changed in the macOS Terminal app that breaks a DNS-based data exfiltration attack chain.
Developers should always consider the context in which model output is rendered and treat that output as untrusted data. An attacker does not necessarily need to trigger a function, shell command, skill, or MCP tool to cause data leakage or other harm. Sometimes, simply rendering attacker-influenced model output is enough to trigger functionality in the surrounding environment.