隱形字元偵測¶
為什麼文字裡會有看不見的東西¶
文件外流追蹤¶
機構要發一份文件給二十個人,於是準備二十份副本,每一份在不同的位置插入不同組合的零寬字元。內容看起來完全一樣,列印出來也一樣,複製貼上到別的地方那些字元還是跟著走。文件外流之後,比對一下就知道是哪一份流出去的。
要轉發手上的文件之前,先掃一遍。
釣魚網址¶
аpple.com 跟 apple.com 看起來一樣,前者的第一個字母是西里爾文的 а。網域註冊商對混用字母的防範不一致,而人眼分辨不出來。
程式碼裡的方向覆寫¶
在原始碼裡放一個右至左覆寫字元,人在編輯器裡看到的順序跟編譯器讀到的可以完全不同。註解看起來包住了一段程式碼,實際上沒有。這類手法有個名字叫 Trojan Source。
幾個真的會遇到的場景¶
記者收到爆料之後的查證動作¶
記者取得一份內部文件,向該機構查證是專業要求。查證時最自然的動作是出示文件,或引用其中一段精確的文字問「這一段是不是真的」。
如果文件是二十份帶不同標記的副本之一,出示或引用查證等於把消息來源交給正在找他的人。每一步都做得很專業,來源卻在查證那一刻被燒掉。
處理順序:
- 收到文件先掃,別急著讀完
- 掃出東西就先清乾淨,留一份原始檔另外收好
- 查證時轉述內容,不要出示文件本身
- 需要引用精確段落時重新打字,不要複製貼上
第四步最容易被忽略。零寬字元跟著複製貼上走,你把那一段貼進查證信件裡的同時也把標記貼了進去。
反方向也成立。媒體內部發給編輯台的稿子、公關公司發給記者群的禁運稿,同樣可能帶標記,用來確認誰提前放了出去。收到禁運稿的人,一樣可能被同一招追出是誰提前外流。
場景的完整脈絡見記者保護消息來源。
組織之間流轉的文件¶
聯合聲明的草稿在幾個團體之間來回、倡議聯盟的內部備忘、公部門發給諮詢委員的參考資料。
這幾種文件的共同點是會被轉寄很多次,而每一次轉寄都完整保留原本的不可見字元。第五手收到的人不知道第一手那份帶了什麼,也不知道自己轉出去之後會被追到誰。
轉給合作夥伴之前掃一遍,成本十秒。
收到的 bridge line 與 onion 位址¶
有人在聊天室貼給你一行 obfs4 bridge,或公告裡放了一個 onion 位址。這兩種都是長串、人眼記不住、只能複製貼上的東西,正好是夾帶隱形字元最方便的地方。
onion 位址用的是 base32,只有 a 到 z 與 2 到 7。任何西里爾字母或不可見字元都不在那個集合裡,貼進 Tor Browser 多半是連不上,而不是連到別的地方。bridge line 的情況比較實在:一長串設定裡夾了不可見字元,會讓解析出錯,或在轉貼過程中被截斷成另一組看起來合理的參數。
真正會「連到別的地方」的手法不在偵測範圍裡:攻擊者可以自己算出一個前綴看起來很像的合法 onion 位址,那裡面沒有任何隱形字元,每一個字都是合法的 base32。分辨它只能逐字比對完整的 56 個字元,或從你信任的來源重新取得。
截圖比複製貼上乾淨,代價要算清楚¶
零寬字元跟著複製貼上走,不會跟著截圖走。所以要轉傳一段來源不明的文字時,截圖比複製貼上乾淨。
代價有三個,都要算進去:
- 截圖丟掉可搜尋性,收到的人不能搜、不能複製其中一段去查證
- 螢幕閱讀器讀不到圖裡的文字,是無障礙上的實質倒退
- 截圖本身帶 metadata,而且很容易連通知列、其他對話視窗、桌面上的檔名一起拍進去
第三項可以處理:用照片 metadata 清除器清掉 EXIF,並且截圖前先看一眼畫面上還有什麼。前兩項處理不掉,只能看場景取捨。
轉給一個人看的敏感內容,截圖合理。要公開發布、要讓人搜尋得到的內容,重新打字比截圖好。
藏在文字裡的 LLM 指令¶
不可見字元可以把一整段指令藏進看起來完全正常的文件、GitHub issue 或 commit message 裡。人讀不到,模型讀得到。
標籤字元區段特別適合藏這種指令:它能把英文一個字元對一個字元編成完全不顯示的內容,長度不限,整段指令都塞得進去。偵測會把標籤字元標成可疑,因為正常文字用不到它們。
為什麼一般人也該在意:你把一段來源不明的文字貼給 AI 助理,藏在裡面的指令會被模型當成輸入的一部分。那段指令可以要求模型忽略前面的話、改變摘要的立場、或在回答裡插入特定連結。你看到的是一段普通文字,模型看到的是一段普通文字加一段指令。
反方向也有人在做:有些工具用零寬字元在 AI 產生的文字裡打浮水印,用來事後判斷某段文字是不是模型寫的。同一種字元,一邊拿來下指令,一邊拿來做標記。
掃過不能證明什麼¶
如果你用完這個工具的結論是「掃過了,可以安心轉發」,那它讓你比不用更危險。
零寬字元是最粗糙的一種標記方式。正因為粗糙,才容易偵測。真正要追人的一方有更多不在偵測範圍裡的做法:
- 每一份副本替換幾個同義詞,「立即」與「馬上」、「大約」與「約莫」
- 調整段落之間的空白行數、換行的位置
- 微調標點,這裡用逗號那裡用頓號
- PDF 裡調整個別字元之間的間距,肉眼看不出,檔案裡是不同的數值
- 頁面上放肉眼難辨的視覺標記,例如某個字的顏色差一階
還有完全不在文字裡的。彩色雷射印表機會在每一張印出來的紙上留下黃點陣列,編碼印表機序號與列印時間,這套機制叫 Machine Identification Code。文件經過列印再掃描之後,你手上那份的來源仍然查得到。
掃描結果能證明的是「有」,不能證明「沒有」¶
掃出東西表示這份文件確實被標記過。掃不出東西只表示沒有用這幾種方式標記,不表示乾淨。
處理真正敏感的文件時,正確的做法是重新打字或轉述內容,不要傳遞原始檔案。
教偵測,不教植入¶
同一套手法,兩種用途。機構要保護內部文件不外流是合理的需求,同一組零寬字元用來找出吹哨者就是壓迫工具。技術本身分不出這兩者,使用它的人分得出來。
社群的立場是:說明手法怎麼運作,讓收到文件的人有能力自保,但不提供產生帶標記副本的功能。
不做的具體包括:把一段文字加上不可見標記的產生器、批次產出多份帶不同標記副本的工具。
「載入示範文字」給的是固定的一段,不能換成你自己的文字。那一段裡有兩個零寬空格、一個冒充網址的西里爾字母、四個標籤字元,讓你看得到偵測結果長什麼樣。示範的教育效果到此為止,沒辦法拿去標記真實文件。想更完整驗證偵測範圍的人,用測試檔裡的案例(tools/test_invisible.mjs)。
立場寫在這裡,方便日後討論引用。
用 Tor Browser 查可疑內容的話¶
Tor Browser 的安全等級調到 Safest 會關掉 JavaScript,偵測功能就會停擺,而收到來路不明的訊息正是那篇文章建議把等級調高的場合。
把可疑的網站與偵測分開處理:在高安全等級下複製那段文字,切回 Standard 貼進來掃,掃完再調回去。掃描在你的裝置上做,不連外。
誤判是這個工具最大的風險¶
不是所有隱形字元都有問題。
👨👩👧 這個 emoji 是三個 emoji 用兩個零寬連字接起來的,那些連字非有不可。變體選擇器是 emoji 的一部分。阿拉伯文與希伯來文本來就需要方向標記。整段俄文裡的 а 就只是俄文。
全部報成可疑的話,警示會失去意義,看幾次之後就沒有人看了。所以它分兩級:橘色是不必看語境就可疑的,灰色是要看前後才知道的。emoji 裡的連字、有 RTL(由右至左書寫)文字時的方向標記,都不會被報成可疑。
測試裡有一整組案例守著不該報的別報,跟「抓得到」那組一樣多。
清理¶
兩個按鈕。一個只清可疑字元,emoji 保持完整。另一個清掉所有看不見的字元,會把 emoji 家族拆散,要的是一份絕對乾淨的文字就選第二個。
同形字不會被自動換掉。那是可見的字,換掉會改變原意,而你可能正在處理一段真的俄文。工具只標出位置與它長得像哪個拉丁字母,換不換由你決定。
離線可用¶
跟這一區其他工具一樣,程式存進裝置之後沒有網路也能用。你貼進來的可能正是不想外流的東西,所以偵測沒有任何網路請求,也不把文字寫進任何儲存,斷網時照樣可以用。
要把這一頁帶著走,見離線閱讀。