chart-scrub 去識別化前後對照:左邊是含姓名、病歷號、生日、電話、地址的原始紀錄,右邊同一筆變成 PT-0001 代號與遮罩標記,主訴與理學檢查完全保留

病歷不能就這樣貼給 AI:我怎麼先把身分拿掉

門診遇到一個有意思的個案,想查一下教科書怎麼講、想跟 AI 對一對自己的鑑別診斷有沒有漏掉什麼。這件事我幾乎每週都在做。 但病歷不能就這樣貼上去。 這跟「我信不信任那家 AI 公司」是兩回事。資料一旦離開這台電腦,它去了哪裡、留多久、被誰看過,就不再是我能決定的事。所以我想要的不是一個更好的承諾,是一個機械上的動作:在資料離開之前,先把身分拿掉。 我把自己在用的那套整理乾淨、開源了,叫 chart-scrub。 程式碼:github.com/drpwchen/chart-scrub 線上試用:drpwchen.github.io/chart-scrub(整頁在你的瀏覽器裡跑,什麼都不會上傳) 它做什麼 一筆門診紀錄丟進去: 病歷號碼:1234567 姓名:王大明 出生:1971/03/05 主訴:右肩痛三個月,夜間痛醒。王大明表示上個月在李阿嬤介紹的推拿館推過。 電話 0912-345-678,住新北市板橋區文化路一段100號5樓。 出來變成: [代號 PT-0001,55歲] 病歷號碼:PT-0001 姓名:PT-0001 出生:[55歲] 主訴:右肩痛三個月,夜間痛醒。PT-0001表示上個月在[稱謂]介紹的推拿館推過。 電話 [電話],住[地址]。 臨床內容一個字沒動,身分不見了。 為什麼不是直接遮成「[姓名]」就好 這是整件事我最先想通的地方。 如果只是把名字換成 [姓名],那同一個病人下次回診、下下次回診,三筆紀錄之間就沒有任何東西把他們串起來了。可是「這個人三個月前打過針、當時有效、這次又痛回來」,這種前後對照本來就是臨床判斷的一部分,弄丟了,剩下的資料就沒什麼討論價值。 所以第一層做的是定向抽換:這個人變成 PT-0001,下次回診他還是 PT-0001。代號對回真名的那張表,只存在我自己電腦上的一個 SQLite 檔,不進雲端、不進筆記庫、也不會給任何 AI 讀。 生日也一樣:直接刪掉可惜,換算成年齡剛好。臨床要的是「55 歲」,不是那個日期。 第二層:一張寧可多遮的網子 定向抽換只能處理「我知道他是誰」的那個人。紀錄裡還會有一堆我事先不知道的東西:電話、身分證、地址、順口提到的其他人。 第二層就是一組正規表示式規則,把這些東西通通遮掉。設計取向很單純:寧可多遮。偶爾誤遮一個醫學名詞,代價是我重看一次;漏掉一個名字,代價大得多。 有一個順序上的細節,是實作時才想清楚的:定向抽換一定要在通用規則之前跑。反過來的話,名字已經先被遮成 [姓名] 了,代號就再也接不上去,跨次就診的那條線也就斷了。 機器自己驗自己 寫完之後我最不放心的是:它到底有沒有真的遮乾淨? 所以最後一步是殘留檢查:程式跑完,拿它自己知道的每一個真名、每一個病歷號,回頭搜自己剛產出的那份輸出。只要有一個活著,這筆就判定失敗、離開碼給 2,我不會拿去用。 另外還有兩個訊號是抓「漏網」的形狀:一個中文姓名黏在已經被遮掉的身分證旁邊、以及長得像身分證卻沒被遮的字串。這兩種都不是「我知道他叫什麼」,而是「這個位置本來就該有東西被處理掉」。 這件事的通則 自動化最怕的不是失敗,是安靜地成功。所以每一段自動化的最後,都值得補一個「回頭檢查自己」的動作,而且要讓它有辦法大聲喊失敗。 開源的過程中,抓到自己三個 bug 這部分我覺得比工具本身有意思。為了公開,我補了測試、逐條檢查,結果揪出三個原本在用的版本就有的問題,而且三個都是那種不會報錯的失敗。 第一個:我習慣的手寫格式是「身分證號+姓名」擠在同一行。但實際的紀錄常常長這樣: 陪同者 A123456789 李小華 程式抓到的姓名是 「陪同者」,不是李小華。因為規則寫成「身分證號旁邊的 2 到 4 個中文字」,而「陪同者」剛好也是三個中文字,還排在前面。結果就是:一個角色詞被登記成病人,真正的名字反而漏掉。修法是要求姓名的第一個字必須是常見姓氏。 第二個:醫院系統匯出的文字檔編碼很雜,UTF-8、UTF-16、Big5 都遇過,所以程式會一個一個試。問題是一個 Big5 檔用 UTF-16 去解,不會出錯,會解出一堆亂碼。而亂碼不會命中任何一條規則,所以程式一路跑到底、印出「全數通過」,實際上它什麼都沒遮到。修法是:只有在檔案真的帶著 UTF-16 的標記時才用 UTF-16 去解。 ...

August 14, 2026 · 1 分鐘 · 130 字 · 陳柏威 Po-Wei Chen
讓 AI 開我的瀏覽器,安全嗎:終端機畫面顯示已對 Kimi WebBridge 封鎖 13 個要害網址,AI 想開網銀得到 Cannot attach to this target,沒被封鎖的網站照常自動化;擴充套件的網站存取權白名單擋不住,要從瀏覽器政策下手

把密碼存瀏覽器、又讓 AI 開瀏覽器,這樣安全嗎?

前幾天一個剛開始用 AI 寫程式的學妹問我一個很好的問題:她讓 AI 直接開她的瀏覽器做事,可是密碼都存在瀏覽器裡,這樣到底安不安全? 我覺得這個問題值得拆成兩層來看,因為大家常常把它們混在一起擔心。認真查完之後,我把答案做成了一個開源工具,文末會介紹。 第一層:密碼存在哪裡 這層其實好解決。不管你是用 Apple 鑰匙圈還是 Bitwarden,只要是專門的密碼管理器,加上重要帳號都開了兩階段驗證(2FA),密碼本身就是安全的。別把密碼記在記事本、別用同一組打天下,這層就過關了。 順帶一提,如果你是把密碼存在 Chrome、靠 Google 帳號同步,要小心:只要有人能登入你的電腦帳號,就能把你存的密碼全部看光,這其實滿危險的。學妹用的是鑰匙圈,這層沒問題。 第二層才是重點:你讓 AI「控制」了你的瀏覽器 這代表它是用你已經登入的身分在操作。你的網銀、你的信箱、你的券商,對它來說都是開著的門。 我用的那套是 Kimi WebBridge。工具本身通常是乾淨的,我實際查過它的控制端:daemon 只綁在本機 127.0.0.1,區網或外網的其他機器連不到;沒有任何對外連線,不會把資料往外送;帶惡意來源的網頁想從瀏覽器裡偷呼叫它,會被擋掉。這部分可以放心。 真正的風險是另一件事,叫 prompt injection:AI 拿著你的登入身分,萬一去讀到一個藏了壞指令的網頁,有可能被牽著鼻子走。它不是被駭,它是太聽話。而它手上握著你所有登入中的網站。 平心而論,這類 AI(像 Claude)本身對 prompt injection 是相當警覺的,最近甚至容易反過來疑神疑鬼、動不動覺得自己被下指令了。但與其把要害帳號的安全全押在它每次都判斷正確,不如多加一道機械上的鎖:把最要命的幾個網站(網銀、券商、Gmail)直接擋在 AI 碰不到的地方,讓它就算被騙也走不進去,其他日常網站照常幫我做事。 直覺的做法沒有用:網站存取權白名單 瀏覽器的擴充套件設定裡有一個「網站存取權」,可以把擴充限制成「只能在特定網站」運作。直覺上把它設好就安全了。 實測結果:攔不住。設好白名單之後,叫 AI 開一個清單外的網站,它照樣進得去、讀得到內容、跑得了 JavaScript。 原因在技術層:這類 AI 瀏覽器控制工具走的是瀏覽器的偵錯介面(chrome.debugger API)在驅動頁面,而「網站存取權」那層設定只管一般的內容注入,管不到偵錯介面。所以那個設定頁面會讓你以為有圍籬,實際上這類工具根本不從那道門走。 順帶說明一下,不是每套工具都這樣:像 Claude in Chrome 是逐個網站問你同意的設計。但只要擴充的權限清單裡有 debugger(WebBridge 這類全站授權的工具就是),逐站白名單就是裝飾品。 真正有效的那道鎖:瀏覽器政策層 往下挖一層,答案在企業環境常用的瀏覽器政策(policy):ExtensionSettings 裡的 runtime_blocked_hosts,可以對指定的擴充封鎖指定的網站。 這道是真的擋得住的。我把自己的網銀、券商、Gmail 一共 13 個登入網址設進去實測:AI 一碰被封的網站就直接吃到 Cannot attach to this target,連頁面都讀不到;沒被封的網站則完全不受影響,日常那些自動化照常跑。兩個方向都要測,這道鎖才算數。 兩個實作上的細節: 只封精確的網址,不用 *.整個網域 這種萬用字元。 封 *.esunbank.com.tw 會連信用卡活動頁一起封掉,而信用卡活動頁、線上表單這類,往往正是你想留給 AI 幫忙的地方。要封的是「登入後能動錢的那個網址」,不是整家銀行。 macOS 有一個陷阱:defaults write 寫進去的政策沒有用,而且是無聲失敗。 實測它在 chrome://policy 會顯示「有效」,但等級只是「建議採用」,AI 照樣進得去;政策要放在 /Library/Managed Preferences 底下、等級顯示「強制」,才真的擋得住。驗證標準要看等級,不是看政策有沒有出現。 做成開源工具:kimi-webbridge-lockdown 這個設定要手動改登錄檔(Windows)或系統政策檔(macOS),有點門檻。所以我把它做成了一鍵設定的工具,開源出來: ...

August 9, 2026 · 1 分鐘 · 142 字 · 陳柏威 Po-Wei Chen