Hidden Characters in Pasted Code Comments: A Review Problem Developers Rarely See
A developer asks an AI assistant to explain a function, pastes the suggested comment block above it, and opens a pull request. The reviewer sees clean prose. Beneath the surface, a few characters have no visible form.
Invisible characters in source files are not new, and they have a serious history in security research. What is new is how often ordinary developers can introduce them through a copy-and-paste from a chat window.
The Security Background
In 2021, researchers at the University of Cambridge published a paper titled Trojan Source, which showed that invisible Unicode control characters can make source code display one way to a human reader while a compiler interprets it another way. The work led several languages and code hosts to add warnings and detection for such characters.
The risk described there involves deliberate attacks. The everyday version is far more mundane, and it is about accidental contamination, not malice. The mechanism is the same: what the reviewer sees and what the machine reads are not guaranteed to match.
How Accidental Contamination Happens
AI chat tools often return formatted text. When that text is copied, invisible characters and formatting metadata can travel with it. Zero-width spaces, non-breaking spaces, and joiners have all been reported in model output, and they land wherever the paste lands.
- Comments and docstrings pasted from a chat window.
- Commit messages and pull request descriptions drafted with an assistant.
- String constants and error messages copied from generated suggestions.
- Documentation and README text that later gets parsed by tooling.
What Can Go Wrong in Practice
A comment with a stray character is harmless to the compiler. A string constant with one is not. An error message that never matches in a test, a configuration key that looks right but is never found, and a diff that shows a change where none is visible are all symptoms.
Why Code Review Does Not Catch It
Review is a visual process. A reviewer reads what the editor draws, and the editor draws nothing for a zero-width character. Diff tools may highlight a changed line without showing what changed. The reviewer approves a change they cannot actually perceive.
Linters can help, but only if configured to flag such characters. Many projects have no rule for it, because the problem used to be rare.
Cleaning Text Before It Enters the Repository
The simplest safeguard is to clean text at the boundary. Running chat-sourced comments and strings through a watermark remover before committing strips invisible characters while leaving the visible words untouched, so the file contains only what the author intended.
Editors can also be configured to display or warn about invisible characters. Combining both habits, clean on the way in and visible markers in the editor, closes most of the gap.
Team Practices That Reduce Risk
Add a check to continuous integration that fails on unexpected Unicode control characters in source files. Include a line in the contributing guide about pasting text from chat tools. Encourage reviewers to enable invisible-character display in their editors.
None of these steps requires distrust of AI assistants. They simply acknowledge that text copied from any rich source can carry baggage, in the same way pasted spreadsheet cells or web page snippets sometimes do.
Where the Tools Live
Developers who want text cleanup alongside drafting and detection tools can find them inside Phrasly AI, which is convenient for teams that also write documentation and release notes.
Configuring Editors and Pipelines
Most modern editors can be set to render invisible characters or highlight unusual Unicode. Turning that on for everyone on the team is a one-time change that makes the problem visible. Pairing it with a continuous integration check that fails on unexpected control characters turns visibility into enforcement.
- Enable invisible-character display in shared editor settings.
- Add a repository check for unexpected Unicode control characters.
- Document the expectation in the contributing guide.
- Review third-party snippets with the same care as pasted text.
A Proportionate Response
None of this calls for alarm. The vast majority of stray characters are harmless clutter, and the point is housekeeping, not panic. The goal is a codebase where what a person reads and what a machine executes line up, and a few cheap habits are enough to keep it that way.
Teams that adopt the habits early report that they rarely have to think about the issue again, which is the best outcome a hygiene practice can offer.
A Note on Proportion and Communication
Teams sometimes hesitate to raise this topic because it sounds like an accusation against assistants or colleagues. It is neither. Text copied from many rich sources can carry invisible characters, and developers have dealt with similar issues from word processors and web pages for decades. Framing the practice as ordinary hygiene keeps the conversation practical.
A short note in the team wiki, with the steps and a link to the repository check, is usually all the communication needed. People adopt a habit quickly when it is easy and when the reason is explained plainly.
Questions Reviewers Can Ask
Reviewers do not need to become experts. A few simple questions during review catch most issues, and they can be added to a pull request template so nobody has to remember them.
- Was any text in this change pasted from a chat tool or a web page?
- Has the text been cleaned of invisible characters?
- Does the linter report any unusual Unicode in the changed files?
- Do string constants match exactly where they are compared in tests?
Why This Is Easy to Overlook
Most developers spend years working without ever meeting an invisible character, so the problem feels exotic. It becomes common only because chat tools have changed how text is produced and copied. The habits that served well before, such as trusting what the editor displays, no longer cover every case.
Adding a small safeguard now costs very little and removes a category of confusing bugs. It is the kind of unglamorous improvement that pays for itself the first time it prevents an afternoon of puzzled debugging.
- Treat pasted text from any rich source as untrusted until cleaned.
- Make invisible characters visible in shared editor settings.
- Add the repository check once and let automation do the rest.
Teaching New Developers the Habit
New team members are the most likely to paste text from a chat window without a second thought, simply because nobody has told them otherwise. A short onboarding note, with the reason and the exact steps, turns the safeguard into a normal part of the workflow. Pairing the note with a visible editor setting means they see the result for themselves the first time a stray character appears.
Experienced developers appreciate being told why, not just what. Explaining that the issue is about the gap between what a reviewer sees and what a machine reads makes the habit feel like sound engineering rather than bureaucracy.
Source code is read by two audiences, people and machines, and invisible characters create a gap between them. A short cleanup step on anything pasted from a chat window keeps that gap closed at almost no cost.
