ByteScope

Invisible Character Checker

貼上文字或丟個檔案進來,看清楚畫面上看不到的每一個字元——零寬空白、Bidi 覆寫、Unicode 標籤、奇怪的空格、藏在英文單字裡的西里爾字母——每個都是一枚帶 code point 的標記,再挑你要的刪掉。

檔案不會離開你的瀏覽器 — 全部在本機處理。

把文字檔拖到這裡

UTF-8、UTF-16 或舊式編碼都可以,最大 20 MiB,也可以點一下選檔。只在這個分頁裡讀取,不會上傳。

文字類型

切換類型只會改變每一筆的嚴重程度,找到的字元不會變。

這個檢查無法告訴你的事

  • 這不是 AI 偵測工具。找到這些字元,不能證明文字是 AI 寫的;沒找到,也不能證明不是。
  • 同形異字只檢查同一個詞裡混用 Latin 和其他文字系統的情況。整個詞都用西里爾字母拼成、假裝成 Latin 的詞(whole-script 偽裝),這一版偵測不到。
  • 零寬字元和變體選擇器在 emoji、波斯文和印度文字裡有合法用途。「看起來是合法用法」只是推測,兩個方向都可能判斷錯。
  • 不偵測字型造成的混淆:l 和 I、0 和 O 都是不同的 ASCII 字元,只是在某些字型裡長得很像。
  • 換成 Latin 的骨架只是 UTS #39 skeleton 的一部分:只替換對應到 A–Z 或 0–9 的西里爾、希臘、亞美尼亞和切羅基字母,也不做 NFD 分解。confusables 資料:Unicode 17.0.0。

關於這個工具

文字裡可以藏著在螢幕上完全不佔位置、卻會改變意思的字元:一個零寬空白讓搜尋對不到,一個由右到左的覆寫字元讓程式碼看起來跟編譯出來的不一樣,一串 Unicode 標籤字元拼出一句只有語言模型讀得到的指令,或是英文單字裡混進一個西里爾字母的 а,連結就跑到別的地方去了。把文字貼進來,或丟一個最大 20 MiB 的文字檔(編碼自動判斷),所有可疑的字元會在原位顯示成 ZWSP、RLO、TAG a 這樣的標記,附上 code point、Unicode 名稱和分類。不上傳,分析全在這個分頁裡做。

會標出哪些

雙向控制字元——U+202A 到 U+202E、U+2066 到 U+2069,以及 LRM、RLM、ALM——這是 Trojan Source 攻擊的手法,審閱者在螢幕上看到的程式碼,跟編譯器讀到的不是同一份。零寬字元:U+200B ZWSP、U+200C ZWNJ、U+200D ZWJ、U+2060 WJ、U+FEFF。Unicode 標籤字元 U+E0000 到 U+E007F,會解回它藏的 ASCII——這是把指令偷渡給 LLM 做 prompt injection 的已知手法。不尋常的空格:NBSP、thin/narrow space、全形空格 U+3000。變體選擇器,一連串出現時可能夾帶隱藏資料。其他格式字元像軟連字號、控制字元、私人使用區的 code point。同形字:混進英文單字裡的西里爾或希臘字母——例如用西里爾的 р 和 а 拼出來的 paypal——用 Unicode UTS #39 的 confusables 資料找出混合文字系統的單字。三種模式(一般文字、程式碼、網址或帳號)只改變顯示的嚴重度,不改變偵測內容。

哪些會被認定是正常用法

不是每個零寬字元都是攻擊。emoji 的 ZWJ 序列(家庭、職業那些 emoji)、國旗的標籤序列、emoji 呈現選擇器、波斯文與印度系文字裡的 ZWNJ 和 ZWJ、中日文裡的全形空格、檔案開頭的 BOM,這些都顯示成資訊而不是警告。「清除」預設刪掉 Bidi、標籤和零寬字元,但會放過上面這些正常用法;同形字只會替換你逐字確認過的單字,因為希臘文句子裡的希臘文單字不是假的。結果可以複製,也可以下載成檔案。

它的限制

找到這些字元,不代表文字是 AI 寫的;沒找到,也不代表不是。網路上很多「ChatGPT 浮水印字元」的說法,其實是普通的排版——不斷行空格、窄空格、長破折號——文書軟體和網頁幾十年來本來就會塞這些進去。同形字檢查只看混合文字系統:整個單字都用西里爾字母拼的,對它來說就是一個正常的西里爾文單字。正常用法的判斷兩個方向都可能出錯。而字型層面的混淆,像某些字型裡小寫 l 和大寫 I 長得一模一樣,那不是 Unicode 的問題,這裡偵測不到。

常見問題

這能判斷一段文字是不是 ChatGPT 或 AI 寫的嗎?

不能。找到這些字元,不代表文字是 AI 寫的;沒找到,也不代表不是。網路上流傳的「ChatGPT 浮水印字元」——不斷行空格、窄空格、長破折號——大多是普通排版,文書軟體、網頁編輯器、從瀏覽器複製貼上,自己就會產生。這頁能告訴你的是:到底有哪些字元、在哪裡。要怎麼解讀,由你自己判斷。

零寬空白是什麼?它怎麼跑進我的文字裡的?

U+200B ZWSP 是一個沒有寬度的字元,標記這裡可以斷行。它通常是從網頁、聊天軟體或某些編輯器複製貼上時帶進來的,平常完全看不見,直到搜尋對不到、帳號被一個「長得一樣」的名字搶走、檔名怎麼都打不開。把文字貼進來,每一個都會顯示成 ZWSP 標記,按「清除」就能刪掉——U+200C ZWNJ、U+200D ZWJ、U+2060 WJ、U+FEFF 這些相關字元也是同樣處理。

Trojan Source 是什麼?怎麼檢查程式碼有沒有中招?

Trojan Source 是把雙向控制字元(U+202A 到 U+202E、U+2066 到 U+2069)塞進原始碼,讓審閱者在螢幕上看到的順序,跟編譯器讀到的順序不同——一段註解可以在視覺上把一行敘述吃掉,一個字串可以在看起來不是結尾的地方結束。把程式碼貼進來、切到程式碼模式:每個 Bidi 控制字元都會在它的位置顯示成標記,「清除」會把它們刪掉。

Unicode 標籤字元是什麼?為什麼會拿來做 prompt injection?

U+E0000 到 U+E007F 是一組跟 ASCII 一一對應的字元,但幾乎所有字型都把它們畫成空白。用它們寫一句話,人在頁面上完全看不到,語言模型對原始文字做斷詞時卻讀得清清楚楚,所以它成了在網頁、文件、聊天訊息裡藏指令的已知手法。這頁會把一串標籤字元解回它拼出來的 ASCII,你看到的是隱藏文字到底寫了什麼,不只是「有東西」。某些 emoji 國旗用的標籤序列是唯一正常的用途,會顯示成資訊。

同形字檢查是怎麼運作的?

它找的是混合文字系統的單字——英文單字裡夾了一個西里爾或希臘字母——用 Unicode UTS #39 的 confusables 資料判斷哪些字母看起來可以互換。用西里爾 р 和 а 拼的 paypal 會被標出來;一句俄文不會,因為每個單字裡的字母全是西里爾文。這也表示整個單字都用西里爾字母冒充英文的抓不到,而某些字型裡 l 和 I 長得一樣這種事,Unicode 本身就說不出來。替換只對你確認過的單字做,永遠不會自動替換。

清除會不會把我的 emoji、波斯文或印地文弄壞?

預設的清除會刪掉 Bidi 控制字元、標籤字元和零寬字元,但有明確用途的會留著:把家庭或職業 emoji 黏在一起的 ZWJ、國旗的標籤序列、讓符號以 emoji 樣式顯示的呈現選擇器,以及波斯文、阿拉伯文、印度系文字裡負責字母連接的 ZWNJ 和 ZWJ。這些會顯示成資訊讓你看見,不會當成要刪的項目。這個判斷是啟發式的,兩個方向都可能出錯,所以貼到重要的地方之前先看一下結果。

我的文字會被上傳嗎?

不會。文字和檔案都在這個分頁裡分析,不會對任何伺服器發請求;20 MiB 的檔案用 File API 讀取,編碼在本機判斷。清除後的結果從記憶體直接複製或下載。所以你最不想送到任何地方的那些文字——一份合約、別人 email 給你的密碼清單、一段你覺得有問題的程式碼——放這裡也沒關係。