A zero-width character attack uses invisible Unicode characters to conceal malicious code within text that appears empty or normal. The characters are valid Unicode that renders with no visual width, allowing attackers to encode complete programs, scripts, or commands that security tools and human reviewers cannot see. The GlassWorm worm (October 2025) and Tycoon 2FA phishing kit demonstrate this technique in active campaigns.
Copy a line of text from a suspicious file. Paste it into your editor. You see nothing, just empty space between two lines of code.
That empty space might contain a complete malware payload. Not hidden in an encrypted archive. Not compressed or encoded in some visible format. Simply invisible. The characters are there; you cannot see them.
Certain Unicode characters render with zero width by design. Attackers figured out how to use them as a binary encoding system.
The 30-Second Detection Test
Before explaining how these attacks work, here is how to check whether a file contains invisible characters right now.
Using a hex editor: Open the file and search for byte sequences E3 85 A4 (Hangul Filler) or EF BE A0 (Halfwidth Hangul Filler). These are the UTF-8 encodings of the most common attack characters.
Online option: Paste suspicious text into a Unicode analyser tool. Any tool that shows code points will reveal invisible characters that your text editor hides.
If you find nothing, the file is likely clean. If you find matches, read on.
How Invisible Encoding Works
The Unicode standard includes characters designed for text formatting that occupy no visual space. A Zero-Width Space marks where a line can break without adding visible whitespace. A Zero-Width Joiner controls whether adjacent characters form ligatures in scripts like Arabic. A Hangul Filler holds position in Korean text grids without displaying anything.
These characters have legitimate purposes. They also have a property attackers exploit: they can represent binary data.
If one invisible character means "zero" and another means "one," you can encode any byte as eight invisible characters. The letter A (ASCII 65, binary 01000001) becomes eight invisible characters. A short script becomes hundreds. A complete payload becomes thousands. All of it renders as blank space.
The most common encoding uses Korean Hangul characters:
Halfwidth Hangul Filler (U+FFA0) = binary 0
Hangul Filler (U+3164) = binary 1
Eight characters encode one byte. The word "hello" becomes 40 invisible characters. A malicious script downloading and executing remote code might be 400-800 invisible characters: appearing as a few blank lines in source code.
The Characters Attackers Use
Different attacks use different invisible characters. Knowing which characters to look for determines what you can detect.
Key Examples
Hangul Filler
Code PointU+3164
Binary Width1 bit
Used ByTycoon 2FA, Juniper PAC campaigns
Halfwidth Hangul Filler
Code PointU+FFA0
Binary Width1 bit
Used ByTycoon 2FA, Juniper PAC campaigns
Zero-Width Space
Code PointU+200B
Binary Width1 bit
Used ByEarly attacks, InvisibleJS tool
Zero-Width Non-Joiner
Code PointU+200C
Binary Width1 bit
Used ByEarly attacks, InvisibleJS tool
Zero-Width Joiner
Code PointU+200D
Binary Width1 bit
Used ByCombined patterns
Variation Selectors
Code PointU+FE00-FE0F
Binary Width4 bits
Used ByGlassWorm (October 2025)
Right-to-Left Override
Code PointU+202E
Binary WidthN/A
Used ByTrojan Source (logic manipulation)
Soft Hyphen
Code PointU+00AD
Binary WidthN/A
Used ByEmail header obfuscation
Character
Code Point
Binary Width
Used By
Hangul Filler
U+3164
1 bit
Tycoon 2FA, Juniper PAC campaigns
Halfwidth Hangul Filler
U+FFA0
1 bit
Tycoon 2FA, Juniper PAC campaigns
Zero-Width Space
U+200B
1 bit
Early attacks, InvisibleJS tool
Zero-Width Non-Joiner
U+200C
1 bit
Early attacks, InvisibleJS tool
Zero-Width Joiner
U+200D
1 bit
Combined patterns
Variation Selectors
U+FE00-FE0F
4 bits
GlassWorm (October 2025)
Right-to-Left Override
U+202E
N/A
Trojan Source (logic manipulation)
Soft Hyphen
U+00AD
N/A
Email header obfuscation
The Hangul fillers are currently most common because they were documented first (October 2024) and adopted by widely-used phishing kits. GlassWorm's Variation Selector technique is more sophisticated, encoding four bits per character instead of one, but requires more complex decoding.
What Attackers Hide
The scope of what invisible encoding conceals is limited only by file size.
JavaScript code — That executes when a webpage loads. The malicious script appears as empty lines in source code. Developers reviewing pull requests see whitespace changes and approve the merge. The payload deploys to production.
Phishing redirects — That email security cannot scan. The destination URL exists only as invisible characters. Pattern matching for suspicious domains finds nothing to match. The link passes security filters.
Supply chain payloads — In software packages. The GlassWorm worm hid an entire remote access trojan within VSCode extension code. Over 35,000 developer machines were compromised before detection because code reviewers could not see the malicious code.
Command-and-control instructions — For malware already present on a system. The infected machine fetches a resource that appears to contain only whitespace. It decodes the invisible characters and executes the commands. Network monitoring sees normal HTTP traffic to legitimate-looking domains.
Credential harvesting code — In phishing pages. The Tycoon 2FA phishing-as-a-service kit uses invisible encoding to hide its JavaScript from security scanners. The code intercepts login credentials including second-factor tokens.
Why Your Security Tools Miss It
Traditional security operates on what it can observe. Invisible character attacks exploit the gap between what exists and what displays.
Signature-based detection — Looks for known patterns. A security rule might flag eval( followed by Base64, or connections to suspicious domains, or known malware strings. When the payload is invisible characters, there are no patterns to match. The signature engine sees empty space.
Code review — Relies on human inspection. Humans cannot see invisible characters by definition. A reviewer examining a diff sees blank lines, assumes formatting changes, and approves. The attacker's payload enters the codebase without scrutiny.
Diff tools — Compare file versions visually. When invisible characters are added, the diff shows whitespace changes at most. Nothing looks suspicious because nothing suspicious is visible.
Static analysis — Parses code structure. But the malicious code does not exist as parseable structure until runtime. The payload is decoded and executed dynamically, often through JavaScript Proxy objects that intercept property access.
Explicit detection for invisible characters is necessary. You cannot rely on tools designed to analyse visible content.
Real Attacks Using This Technique
GlassWorm (October 2025) — The wake-up call. A worm spread through VSCode extensions, compromising 35,000+ developer machines. Koi Security found the malicious code was completely invisible when viewing extension source files. The worm stole GitHub tokens, npm credentials, and cryptocurrency wallets.
Tycoon 2FA (2025) — A phishing kit used by criminals worldwide added invisible encoding to bypass security scanners. Trustwave SpiderLabs documented the technique. Thousands of phishing pages now use it.
Juniper PAC Campaign (February 2025) — Targeted attacks against American political organisations. Juniper Threat Labs found invisible JavaScript in spearphishing emails containing non-public personal information about targets.
Trojan Source (2021-Present) — CVE-2021-42574. Uses different invisible characters to make code appear to do one thing while actually doing another. Still exploitable five years later.
Awareness changes your approach to suspicious files. Blank space is no longer obviously safe.
When analysing suspicious scripts — Check for invisible characters before concluding a file is benign. The detection commands at the beginning of this article take seconds to run.
When reviewing code changes — Be suspicious of commits that appear to contain only whitespace modifications. Whitespace-only changes in source files are unusual. Invisible payload injection would appear exactly this way.
When configuring development environments — Implement pre-commit hooks that reject files containing invisible Unicode characters. Most codebases have no legitimate reason to include Hangul fillers or Variation Selectors.
When investigating phishing — Recognise that the visible page source may not show the complete payload. Tools that display character code points reveal what standard views hide.
When responding to suspected compromise — If you find invisible encoding, treat it as intentional. Legitimate code does not accidentally contain hundreds of Hangul filler characters. Initiate incident response procedures.
The Path Forward
Invisible Unicode obfuscation exploits a fundamental gap: security tools and human reviewers operate on what they can see. Attackers recognised that encoding data in characters that do not display creates a visibility asymmetry they can exploit.
The twelve months from proof-of-concept (October 2024) to supply chain compromise (October 2025) demonstrated how quickly novel techniques become operational threats. GlassWorm's blockchain-based command-and-control shows attackers are innovating rapidly.
Defence requires explicit detection. The patterns are known. The tools exist. Implementation is the remaining gap.
KlaroSkope automatically detects and decodes invisible Unicode character encoding, then continues through nested Base64, hex, and XOR layers to reveal the hidden payload. Try KlaroSkope Free →
Frequently Asked Questions
Q
What is a zero-width character?
A zero-width character is a valid Unicode character that occupies no visual space when displayed. Examples include Zero-Width Space (U+200B), Hangul Filler (U+3164), and Variation Selectors (U+FE00-FE0F). These characters exist for legitimate text formatting purposes such as marking line break opportunities and controlling ligature formation. Attackers repurpose them to encode hidden data by assigning binary values to different invisible characters.
Q
How does invisible Unicode encoding hide malware?
Attackers use pairs of invisible characters to represent binary digits. For example, Halfwidth Hangul Filler (U+FFA0) represents 0 and Hangul Filler (U+3164) represents 1. Eight invisible characters encode one byte. A complete malicious script becomes hundreds or thousands of invisible characters that appear as blank space in text editors and code viewers. The payload is decoded at runtime by JavaScript that converts the invisible characters back to executable code.
Q
What was the GlassWorm attack?
GlassWorm was a self-propagating worm discovered in October 2025 by Koi Security that infected VSCode extensions on the OpenVSX marketplace. It used Unicode Variation Selectors to hide malicious code that was completely invisible when viewing extension source files. The malware compromised over 35,000 installations, harvesting developer credentials for GitHub, npm, and cryptocurrency wallets. It used Solana blockchain transaction memos as command-and-control infrastructure, making takedown impossible.
Q
Can I see invisible characters if I look carefully?
No. Zero-width characters render with no visual representation by design. Standard text editors, code viewers, and diff tools display them as empty space. To see them, you need specialised tools: hex editors that show raw byte values, Unicode analysers that display code points, or command-line utilities with Unicode-aware pattern matching.
Q
How do I protect my codebase from invisible character injection?
Implement a Git pre-commit hook that scans for invisible Unicode characters and rejects commits containing them. Add CI/CD pipeline checks that fail builds if invisible characters are detected in source files. Most codebases have no legitimate reason to contain Hangul fillers, Variation Selectors, or BiDi override characters. Blocking them proactively prevents attackers from using this technique in your repository.
Q
What is the difference between invisible encoding and Trojan Source?
Invisible encoding hides complete payloads in characters that do not display. Trojan Source (CVE-2021-42574) uses bidirectional override characters to manipulate how visible code displays versus how it executes. With invisible encoding, the malicious code is literally invisible. With Trojan Source, the malicious code is visible but appears to do something different than it actually does. Both exploit Unicode properties, but the attack mechanism differs.