Steganography in AI Coding Tools: How System Prompts Can Silently Collect Environment Data, and How to Detect It
An overseas AI coding tool has been accused of embedding a hidden mechanism that probes developers' environments and encodes the results as invisible characters in the system prompt, which are then sent back to the server. This article analyzes the mechanism as a four-layer covert channel (collection, classification, homoglyph encoding, and exfiltration) that encodes signals such as proxy targets, timezones, and AI lab affiliations with a capacity of only about 2.58 bits. It also explains how to detect it with a pre-request audit hook, differential traffic testing, binary baseline checks, and egress auditing. Finally, it presents compliance principles for vendors, risk-control measures for enterprise adopters, and a line between legitimate regional restrictions and covert data collection.
1. The Core Dispute: Not “Detection,” but “Silent Encoding and Exfiltration”
The current industry debate centers on an overseas AI coding tool accused of embedding a covert environment-probing and signaling mechanism. The dispute is not over whether a tool inspects the runtime environment. Many tools legitimately collect data such as timezone and proxy configuration, for example to localize time display or troubleshoot connectivity. What is genuinely concerning is what happens next: the probe results are not used for any user-visible feature. Instead, they are encoded into invisible characters in the system prompt and sent to the server along with the request.
According to public reverse-engineering analyses, this logic first appeared in version 2.1.91, released in April 2026. That release’s notes did not mention these checks at all. In later versions, the relevant functions exist under obfuscated short names such as Crt(), Rrt(e), e0t(), and Zup(). The logic is also XOR-obfuscated and embedded in the binary, which prevents static string scanners from extracting it.
Three technical criteria are commonly used to judge whether software qualifies as “spyware.” This case meets all three:
- Collection scope exceeds functional necessity. The tool probes the domain attributes of the proxy destination. It also checks whether they are linked to AI research institutions in a specific country. None of this relates to core functions such as code completion or formatting.
- The transmission path stays outside the user’s view. The information never appears in logs, never shows up in the interface, and feeds into no decision. It is only uploaded in encoded form.
- Active evasion of detection. The tool relies on code obfuscation, omits the behavior from release notes, and uses visually identical Unicode code points.
2. How the Chain Works: A Covert Channel in Four Layers
Abstracted out, this mechanism is a textbook covert channel:
[Collection layer] read environment variables → [Classification layer] tag the results → [Encoding layer] homoglyph substitution → [Transmission layer] sent to the server with the request
The collection layer makes two kinds of checks. The first is timezone. It reads the TZ environment variable and the system timezone. It then checks whether they fall within a set of in-region identifiers (such as Asia/Shanghai or Asia/Urumqi, both used in mainland China), which it uses to infer where the user is located. The second concerns the proxy’s target attributes. It parses the URL the proxy points to and checks whether it is an in-region domain, matches a built-in allowlist, or is linked to specific AI research institutions.
The encoding layer is the most elaborate and most problematic part of the design. System prompts usually contain a line like Today's date is .... The approach documented on the Anthropic side changes two spots in that line at the same time:
| Check result | Date separator | Apostrophe code point | Character name |
|---|---|---|---|
| Only the timezone is in-region | - → / |
unchanged | — |
| Domain not in-region or not allowlisted, but linked to an AI lab | - |
' → ʼ |
U+02BC MODIFIER LETTER APOSTROPHE |
| Domain in-region or allowlisted, and linked to an AI lab | - |
' → ʹ |
U+02B9 MODIFIER LETTER PRIME |
| Domain in-region or allowlisted, not linked to an AI lab | - |
' → ’ |
U+2019 RIGHT SINGLE QUOTATION MARK |
In most monospaced fonts, these characters render almost identically to the ASCII apostrophe. They are hard to spot by eye, even after the text is copied into an editor. The server, however, only needs to run a byte-level comparison on the request body to losslessly reconstruct the user’s profile tag.
A number worth working through: the date separator has 2 possible values and the apostrophe has 3. That gives 6 distinguishable states, or a channel capacity of roughly log2(6) ≈ 2.58 bit. This matters because that capacity is not enough to exfiltrate any meaningful text or code. It is more than enough to encode a coarse-grained user segmentation label. In other words, the design sits precisely at the balance point between “just enough” and “invisible.”
A third risk is often overlooked. Because these characters sit inside the system prompt, the path is more than a covert channel. It is also a prompt injection surface. Any character silently written into the system prompt is received verbatim by the model. In theory, this could affect how the model handles formatting, language, or refusal policies. The covert channel and behavioral manipulation share the same path.
3. How to Detect It: From a Five-Minute Script for Solo Developers to Routine Checks for Enterprise Teams
1. A pre-request audit hook (lowest cost, highest payoff)
You don’t need to reverse engineer the tools you use. Just intercept the request body at the HTTP egress point and make the system prompt “visible”:
import unicodedata, logging# Blacklist of common hidden / homoglyph characters# (can be extended to cover the whole family of Cf-category zero-width characters)SUSPECT = {0x2019: "U+2019 RIGHT SINGLE QUOTATION MARK",0x02BC: "U+02BC MODIFIER LETTER APOSTROPHE",0x02B9: "U+02B9 MODIFIER LETTER PRIME",0x200B: "U+200B ZERO WIDTH SPACE",0xFEFF: "U+FEFF ZERO WIDTH NO-BREAK SPACE",}def audit_system_prompt(text: str) -> list[str]:hits = []for idx, ch in enumerate(text):code = ord(ch)if code in SUSPECT:hits.append(f"offset={idx} {SUSPECT[code]}")elif unicodedata.category(ch) in ("Cf", "Co", "Cs"):hits.append(f"offset={idx} U+{code:04X} category={unicodedata.category(ch)}")# If NFKC normalization changes the content, suspect compatibility-character substitutionif unicodedata.normalize("NFKC", text) != text:hits.append("Content changed after NFKC normalization; suspected homoglyph substitution")return hits
2. Differential verification: don’t judge from a single version
From the same machine, send requests once on a direct connection and once through a proxy. Capture the full outbound traffic from both and diff it. If differences appear in fields that should not vary with the network environment, such as the system prompt, and the differences consist only of invisible characters, that is close to conclusive. This step requires no reverse-engineering skills, only packet capture and comparison.
3. Binary baseline verification
Enterprise teams should maintain a hash allowlist for their toolchain and verify it after every automatic update:
# Compute the hash after an update and compare it with the baseline (illustrative)sha256sum /opt/devtools/bin/tool > after.sha256diff baseline.sha256 after.sha256 && echo "OK" || echo "Tool binary has changed; manual review required"
You should also extract the symbol table and strings from suspicious versions. Look for large numbers of meaningless short function names (such as Crt, Rrt, and e0t) and for XOR-obfuscated string constants. Obfuscation by itself is not malicious. But obfuscation + undisclosed changes + network probing together warrant an immediate increase in the risk rating.
4. Egress auditing
At the gateway, record the outbound domains of tool processes and a baseline for their request volumes. Requests that recur periodically with unusually stable volume are often the fingerprint of signaling exfiltration.
4. A Measured Assessment: Distinguishing Capability, Allegation, and Fact
Methodological restraint is essential here. The evidence currently shows that the community has completed a reverse-engineering reproduction, but the vendor has not given a formal response, and independent third-party verification is insufficient. The rigorous wording is therefore “a suspected covert collection mechanism with strong evidence,” not a settled verdict.
It is also fair to acknowledge what is reasonable in the vendor’s position. Terms-of-service geographic restrictions, intellectual property protection, and export control compliance are real commercial and legal constraints. Vendors have the right to limit the scope of their services under their terms. The dispute is not over whether they may restrict, but over how they restrict.
With an explicit technical approach, region checks are visible. For example, at startup the tool can tell the user that the current region is not supported, and the user can then accept or decline. With steganographic encoding and exfiltration in the system prompt, the user cannot even perceive that they have been denied, let alone give informed consent or make a choice. The line between the two is clear.
From this follows a general boundary principle. It applies equally when evaluating any tool’s “future capabilities”:
Once a system is shown to be able to silently rewrite its system prompt and send information back in response to certain environment attributes, the same path could in theory be used to collect hostnames, internal network addresses, code repository fingerprints, or dependency lists. It could even be used to deliver targeted prompts. The risk lies not in the behavior that has already occurred, but in the existence of that path itself.
5. Compliance Design Principles for Vendors and Risk Controls for Enterprises
For tool vendors, four principles should go into the design review baseline:
- Informed consent first. Any environment probing beyond core functionality must have a separate, explicit authorization entry point that users can decline, and it should be off by default.
- Minimum necessary. If judging “is this a supported region” is enough, don’t also judge “which institution is it linked to.” Limit collection granularity to the minimum the function requires.
- Purpose limitation and auditability. List each collected item, its use, and its retention period in the documentation. Any change must be included in the release notes.
- Reproducible builds + third-party security audits. Allow enterprise customers to verify binary hashes and perform their own diff reviews.
Mainstream cloud platforms usually take a different approach to governing toolchains like these. They put region and compliance checks in an explicit server-side authentication step, backed by unified logging, monitoring and alerting, and least-privilege access control so that the whole chain is traceable. Examples include the general-purpose log auditing, observability, and access control capabilities offered by cloud platforms such as Baidu AI Cloud. They do not rely on covert encoding in the client. This approach is not weaker in security terms, and it naturally meets auditability requirements.
For enterprise adopters, five controls are worth putting in place:
- Add AI coding tools to the software supply chain inventory, lock versions, and disable automatic updates. Require a security review for any change.
- On the egress side, set up a domain allowlist and a request-volume baseline, and alert on anomalies.
- Inject a unified “system prompt visibility” audit at the gateway layer, and treat it as a routine check.
- Do not let sensitive codebases connect directly to the internet through third-party tools. Where necessary, route traffic through internal proxies and data-masking gateways.
- Periodically check whether the tool’s privacy statements match its actual outbound behavior. Use “statement–behavior consistency” as a metric in vendor evaluation.
6. Conclusion
The real value of this controversy is not any single vendor’s choice. It is that it has brought a long-overlooked problem into the open. When a tool’s “environment awareness” happens outside the user’s view and uses invisible characters as its transport, every link in the trust chain needs verifiable technical means as a backstop.
For individual developers, a 30-line audit script is enough to surface hidden characters in the logs. For enterprise teams, baseline verification plus egress auditing covers most of the risks. For every vendor, the answer is quite simple: any collection should be visible, understandable, and refusable to the user.
