隨意聊

有別於其他的長文,這裡都是比較隨意寫的短文。原本是發在臉書粉專,但都藏在臉書裡面有點可惜,索性搬一份到部落格來,對不用臉書的人也更友善。

共 110 篇 第 2 / 6 頁 RSS 訂閱

Snaps 簽交易漏洞

在加密貨幣的世界中,MetaMask 大概是最知名的軟體錢包了。而 MetaMask 除了本身提供的那些功能以外,還提供了叫做 Snaps 的 plugin 系統,可以讓開發者在 MetaMask 上面新增功能。

MetaMask 是瀏覽器的 plugin,然後本身又提供了 plugin,一層疊一層,厲害吧。

那有什麼功能會需要往 MetaMask 上面加呢?

舉例來說,有些 blockchain 用的技術沒有被 MetaMask 原生支援,因此這些鏈如果想做錢包的話,要嘛自己再做一個新的擴充套件,要嘛用 Snaps 加到 MetaMask 上。

由於 MetaMask 實在是太多人用了,因此大多數人都選擇後者,做一個 plugin 來幫它加功能,讓它支援更多種不同的 chain,例如說 MetaMask 背後的公司 Consensys,就做了個給 Starknet 用的 Snaps 錢包,讓大家可以在這上面使用 Starknet。

今天有份漏洞報告被揭露,有人發現這個 Starknet Snaps 在發起交易時,支援一個叫做 enableAuthorize 的參數,正常狀況下是 true,MetaMask UI 就會顯示確認視窗。

但如果這個參數傳 false,就不會顯示確認視窗而是直接 sign transaction。換句話說,如果有人不小心在某個網站上連接了 Starknet Snaps,在連接之後攻擊者就可以直接用這個參數繞過確認,在使用者不知道的狀況下發起交易,進而把裡面的錢偷走。

而這個「連接」就像是你在網站上要使用 MetaMask 錢包會跳出的視窗一樣,不是個太敏感的操作(我認為啦),網站要拿錢包地址也需要先連接,否則什麼都拿不到。這個連接跟授權交易完全是兩回事,前者雖然要使用者點擊,但門檻低。

總之呢,假設我做了一個 Dapp 跟大家說來連接 Starknet Snaps 就送獎金,只要連接拿地址登記就好,散佈出去,若是有人裝了這個 Snaps,在點擊連接後就能自動幫他簽交易把錢偷走。

問題來了,這樣的漏洞嚴重程度是多少,賞金又是多少呢?

答案是 medium 以及 350 塊美金 😆

原本 Hackerone 的人員還評估成 low,之後是 Consensys 的人改成 medium,但我怎麼看至少都應該是 high 才對。

官方給的理由是:

  1. 使用者必須有裝Starknet Snap
  2. 使用者要 connect
  3. downstream dApp behavior for financial impact

第一點簡直是聽君一席話如聽一席話的典範,我不就是回報這個程式的漏洞嗎。

第二點我上面講過了,我覺得門檻沒這麼高。

第三點我就沒有看懂了,不知道是不是我對 Starknet 了解有誤?在我的認知中,只要能簽交易就能偷錢了,我自己做個惡意 dApp 不就好了嗎?難道不是?

總之,在我反駁之後官方沒有繼續給回覆,我就請求公開漏洞了,官方還是沒回覆,因此現在一個月後自動公開。他們很多漏洞都沒公開的,我猜他們可能連看都不看根本不 follow 了,也沒有管後續 😂

喔,對啦,那個回報的人就是我,碰巧看到的洞而已。,歡迎一起來看看報告。

然後另一個我覺得滿值得聊的是 CVSS 對於 Web3 的適用程度,我都可以偷錢了,結果拿 CVSS 給我評個不影響 confidentiality 跟 availability,然後 integrity low。

你要這樣講不是不行啦,我只能簽交易確實可能不影響那些,但這個洞怎麼看都不會是 low。這代表在 Web3 相關的情境下,針對傳統漏洞的 CVSS 沒辦法很好的判斷嚴重程度,沒有把資產損失這點考慮進去。

而大多數時候我也不會看到有人硬要把 CVSS 拿去套那些加密貨幣的漏洞,至於 hackerone 為什麼堅持這樣,我也不知道 😑

AI 軟體開發第三時代

早上看到 Cursor 的部落格發了一篇文章《The third era of AI software development》,裡面把 AI 軟體開發分成三個時代,覺得滿贊同的來聊一下,順便寫一下上次提的用 AI 做逆向工程的心得。

第一個時代是 Tab 自動補完,也就是最早期的 GitHub Copilot 在幹的事情,當初 Cursor 剛出來的時候也是這功能。

第二個時代是 AI agent,也就是現在大部分軟體工程師都在幹的事情,讓 AI agent 幫你寫 code。在一年前的時候,使用 Cursor tab 的人是 agent 的 2 倍,而現在已經顛倒過來了,我自己也很少用 tab 了。

而第三個時代就是我上週提過的 Cloud agents,本地用 agent 有其限制,例如說某些資源還是共用,同時也沒辦法真的開到太多太多 agent,還是一個我認為滿重要的限制是「你要有台電腦」。

而 Cloud agent 就是最理想中的形式,你只要在 web 介面上說一句話,背後就有 agent 去幫你開發,跟在本機電腦一樣。幫你開發完測完之後,你去 review 就好。

這個第三個時代的轉變,讓我們脫離了「一定要有電腦」這個限制,你在下班回家的捷運上突然有個 production issue,打開 cloud agent 叫他分析 log 然後把 bug 修掉,發 PR、merged、deploy,可能你還沒到家事情就解決了。

其實已經有不少人現在就是走這個開發模式了,大多數我看到的是一些熱情投入 AI 的個人開發者,至於公司的話,之前提過的 Stripe 就是,一定還有別的公司也是只是我懶得找。

不過第三個時代的門檻較高一點,你要先把開發環境準備好,而且還要同時有多個,不像第二個時代你都跑在自己電腦上,自己建好就行。或許再過個兩年,大多數人都會進入第三個時代,把大部分開發都丟到雲端去,隨時隨地都可以 coding。

想先體驗這個時代會長怎樣的,現在就可以找一些工具來用了(如上次介紹的 Cursor cloud agent),這是現在就做得到的事情。某個層面有點類似 OpenClaw 小龍蝦那樣,你給他環境跟機器,下指令他就會做事。

最後來寫一下用 AI 逆向工程的心得,我對逆向工程幾乎沒研究,除了學生時期修組合語言的時候,期末 project 做的是逆向某個小軟體,把 jmp 改成 nop 以外,就沒碰過逆向了。

這次因緣際會拿到一個 Golang HTTP server 的 binary,想說來試試看現在結合 AI 可以做到什麼地步。一開始我直接先召喚 agent 出來,它就先用 strings 去猜各種字串,最後撈到一些參數跟 URL,其實也滿有用的。

但這樣還不夠,於是我裝了個 Ghidra MCP 再裝了個專門分析 Golang 的 plugin,再搭配我平常在用的 Cursor,直接在上面跟他說「幫我逆向這個程式並給我一份報告」,他就產出了一份報告說明這是什麼東西,然後把 API endpoints 都列出來。

那時我可以感受到跟外行 vibe coder 相同的喜悅,也就是「我以前認為這麼困難的領域,沒想到靠 AI 就能讓我產出成果,AI 太神啦」,不過我對逆向工程還是抱持著一顆敬畏的心,依舊佩服那些會這個技能的人。同時,我也不覺得 AI 在這件事情上可以完全取代人類,AI 逆向出來的結果有些是錯的,有些也有幻覺,還有進步空間,我給的也只是隻小程式,沒試過更複雜的。

詳細的心得跟步驟昨天寫在部落格了,有興趣的可以看一下。總之呢,心得就是 agent + MCP 組合技真的好用,大力推薦。

雲端 Agent 開發時代

現在業界對於 AI coding 的使用,到底是怎麼個用法呢?剛好最近看到一些可以連起來的東西,簡單寫一下。

金流服務 Stripe 最近發了一篇文章,介紹他們自己打造的內部工具 Minions,你可以直接從 Slack 上面 tag 他,跟他說要做什麼,他就會自己起一個環境(內部叫 devbox,一個 EC2 instance 上面已經把環境弄好 ),把任務完成之後發 PR 讓你 review。

然後他們用的 coding agent 是從開源專案 goose fork 出來改的,看來大公司還是有挺多東西需要客製化的。

在兩三年前雖然也有這種概念(AI 軟體工程師如 Devin),但在當時看來我還覺得有點遠,模型還沒這麼厲害,但是在 2026 的現在,是 100% 可以做到的東西,更是有些公司內部已經在使用的服務。

但不要看 Stripe 做得到,就以為每間公司都行,要這樣做至少要有兩個前提:
(1) 你的測試要足夠
(2) 你要能把環境建起來

Stripe 是因為本來就有很多測試,所以 AI 改壞可以自己修,直到測試通過為止,人 review 的時候可以減少很多心智負擔,因為 test coverage 夠齊全,至少不會歪到哪去。

但很多公司連測試都沒有,想這樣做要嘛工程師花些心力 review,要嘛相信 AI 足夠強,直接勇敢按下 merge。

剛好這兩天 Cloudflare 宣布他們用 AI 花了一週把 Next.js 遷移到 Vite 上面,然後只有一個工程師在負責指揮,就搞定了。

在他們的文章中也有清楚提到,這次遷移能順利的理由是完整的 AI 文件以及全面的測試案例,否則不可能這麼順利。這個再次強調了測試的重要性,當你的測試夠強,就能讓 AI 自主工作變得更有效率。

現在已經很多人直接 claude code 或其他 AI agent,跑一次就把任務完成了,而 Stripe 那種模式可以想成把你的本地環境搬一份到雲端,就可以享受隨時隨地叫 AI 工作的快感。

那如果你也想體驗這種快感該怎麼做呢?

剛好這兩天 Cursor 的 Cloud Agent 改版,它就是一套雲端的 agent,我已經體驗過了,感覺很不錯。

把 GitHub repo 權限開給他以後,agent 會自己從 repo 中去探索怎麼把服務跑起來,然後還會錄影片給你證明它完成了。若是 agent 卡住,你可以中斷它然後幫他操作,這邊是直接有一個雲端桌面可以操控,一個 Xfce 的 Linux 環境。

比如說像我的專案需要登入,在 setup 過程中 agent 發現後就自動在 setup 區塊說他需要帳號密碼,直接多了兩個輸入框出來讓我填。

在環境配置好以後,就會存 snapshot,之後每個任務都只要出一張嘴,agent 就會自己把環境跑起來,然後完成你交代的任務,之後發 PR 等你 review,就像是 Stripe 的文章中所描述的那樣。

整體的體驗滿不錯的,專案建置上沒什麼問題,Electron 它也跑得起來。只是在操控上面因為是用 computer use 所以滿燒 token,我今天讓它試著在 desktop app 上做一個新功能,大概花了 30 分鐘,燒了 2000 萬個 token,似乎是 10 美金左右。

未來 cloud agent 我猜也會越來越普及,只是在資安以及環境建置這塊要怎麼處理會比較麻煩(例如說有些服務在公司內網),但用起來感覺不錯就是了。

總之呢,從我自己的日常開發以及這些大公司的部落格中,很明顯可以看到軟體工程師把任務交給 AI 跑已經是常態了,不要再用什麼網頁版,你用 claude code 也好 open code 也好 Codex 也好 Cursor 也好,反正有個 agent 可以幫你跑任務就對了。

我自己日常開發還是用 Cursor,下次再寫一篇我最近怎麼用 Cursor 搭配其他工具,幫助我這個外行人逆向一個 golang binary 吧。

用 CSS 寫出 CPU

有寫過網頁的人可能知道 CSS 很厲害,可以用純 CSS 來寫遊戲,無論是 2D 或 3D 的都行。

但我今天看到了個更厲害的,用 CSS 寫了個 x86 CPU 模擬器!把 C compiled 變成 machine code 之後,可以把它交給 CSS 去跑。

有點類似於有些人在 Minecraft 裡面也會搞出一台電腦或是 CPU,不過弄在 CSS 上從我的角度看來是更厲害的,因為它能用的東西更少一點。

至於原理的話,作者之後會寫個部落格談談自己用到哪些技巧,目前看起來是受兩年前另一篇文章《Expert CSS: The CPU Hack》的啟發,透過 animation + keyframe 為基礎去弄出一個 loop,剩餘的就是一堆計算跟儲存了。

補充文章:https://garethheyes.co.uk/

手機定位與 AI 洗稿

剛剛在讀一篇之前存起來的文章《Your Phone Silently Sends GPS to Your Carrier — Here’s How》,內容大意是手機的組成分成兩塊,一塊是應用晶片(Application Processor, AP),大家常用的 iOS/Android 都在這上面,另一塊是基頻晶片(Baseband Processor, BP),負責處理 2345G 那些手機原有的通訊功能。

而 BP 上有個 protocol(RRLP/LPP)可以讓電信商拿到你的 GPS。由於是在 BP 上,所以不是 Android 跟 iOS 這些應用層可以干涉到的,就算你把什麼權限都關了也沒用,它是直接從更底層去拿的。這功能的本意是在緊急狀況時能夠有方法定位到手機,因此有了這個協定,但既然這功能是存在的,就代表會有被濫用的可能性。

文中有舉了一些例子,例如說在美國經過法院許可之後就可以跟電信業者去申請(不過標準不太統一)以及美國電信業者之前出售 GPS 資料的新聞等等,還有以色列在疫情時也運用手機定位去做隔離。

文章最後則是提到 Apple 從 iPhone 16e 開始自己做了 BP 的晶片(C1 Modem),所以可以突破 AP 跟 BP 間的隔離,提供了針對位置隱私的防護措施,能夠限制可以取得的數據。

看完之後,我第一個想到的是中華電信在疫情時也有過類似的新聞,查了一下說是透過基地台定位,沒有提到更具體的技術:

利用手機和基地臺之間的相對位置概略定位,電信業者定時監測手機所連接的基地臺

以色列當時所做的類似措施,也沒有提到具體技術,所以也不知道是透過基地台去定位,還是真的用了前面提過的 LPP 協定去定位。

接著我想找更多相關討論,於是拿標題去 google,反而找到了另外一篇《Mobile carriers can get your GPS location》,內容提到的東西與開頭看的那篇極為雷同,但是順序不一樣,這篇是先提 Apple 的那個新措施,然後才講到那兩個通訊協定,以及實際追蹤過的範例。

這篇發文的時間是 1/31,開頭那篇發文時間是 2/1,讓我開始思考,會不會我原先看的那篇,其實是這篇經由 AI 改寫並且補充的版本?

我目前唯一能找到的間接證據是文中有一個「HAR2009」的連結引用,點下去是 404 Not Found,這個連結會在短短一個月內突然失聯的機率偏低(用 Wayback Machine 查過了,上次存檔就在 2009),有沒有可能是 AI 寫完之後作者沒確認就放進來了?如果是真人寫的,應該不會放個 404 才對。

不過除了這兩篇提到的東西真的很雷同以外,目前也沒有其他一刀斃命的證據可以證明什麼,只是我的懷疑而已。

沒想到只是看個 GPS 追蹤的文章,還可以弄出個案外案(?)

總之呢,我的感想是:

  1. 不管實際是用什麼技術(三角定位也好,古老協議也好),電信公司都有能力可以追蹤你的位置(但我還是滿想知道具體到底是不是用到這個 protocol)
  2. 有沒有可能以前看過的好文章,是 AI 洗稿而來的?或更進一步思考,AI 改寫的比原文好的話,身為讀者我該用什麼心情去面對?

Typeless 隱私檢查

有個叫做 Typeless 的 app,就如同其名一樣,希望讓大家從打字中解放,用語音輸入就可以把許多事情搞定。據說很好用,用的人不少,但近期有人指出可能有些資安上的疑慮,因此我好奇把它拆開來看了一下。

話說在這個人手一個 AI agent 的時代,其實把它拆開來很容易,你就跟你的 AI agent 說它是個 Electron App,它就會找到 asar,解開,然後分析裡面的 JavaScript。就算不講它是 Electron,我相信 AI 應該也能判斷得出來。

首先是語音辨識的部分,是 100% 雲端沒錯,你的語音輸入外加 context 都會被送到他們的 server。不過這點其實他們官網就有寫,我預期使用者在用之前應該也會知道?

Cloud Processing: Transcription is performed on the cloud to ensure the highest accuracy and low-latency performance.

但在安裝使用的時候,確實有一行標題寫說:「所有數據保持本地」,敘述是「所有歷史紀錄都保留在你的設備上」,這倒是有一點誤導,敘述是對的,但標題的「所有數據」並不包含你的語音。

然後順帶一提,還有一個標題寫「零數據保留」,根據我的淺薄理解,零數據保留其實跟雲端是不衝突的。你可以把資料傳到雲端,但 service provider 又宣稱沒存你的數據。

至於是不是真的呢,第一看你信不信任這間公司,第二看有沒有拿什麼第三方合規認證,這就見仁見智了。很多大公司的雲端產品也都有零數據保留相關的 policy。

把話題拉回來,那 Typeless 除了語音辨識以外還會幹嘛呢?看了一下,主要就是收集語音辨識時需要的 context,這 context 包含現在 focus 的應用程式、標題、URL(如果是瀏覽器)、input 內的文字以及當前畫面能看到的文字等等,具體請求內容我放截圖了,這是我在 Github Issue 上面留言,所回傳 server 的資料。

我自己是覺得這些 context 還算合理啦(儘管完整 URL 跟 visible screen content 應該有些人會覺得有點可怕),就真的是語音辨識的時候需要用到,藉由這個 context 能讓結果更強。

至於按鍵監聽的部分,是拿來做熱鍵偵測沒錯,但我也不確定常見做法是什麼(Electron 也有內建,不過我沒用過),至少沒看到把按鍵資訊直接回傳。

總而言之呢,作為一個立志要讓語音辨識變得超好用的 app,目前的 context 看起來還算合理,至少從原始碼中沒看到它偷傳什麼奇怪的資料,不過有幾點是肯定的:

  1. 語音會被傳到 server
  2. context(內容見附圖)會被收集並傳到 server

知道這些以後要不要使用,就看每個使用者自己了。

有些人覺得這些資料是合理的,是必要的,就繼續用。有些人可能覺得它拿的東西太多,或甚至有些人希望語音永遠留在本地不要上雲,這都是每個人的選擇。

然後我也只是隨便看了幾眼,程式碼靠 AI 幫我先看過一輪我再稍微對照,只確認了一下請求格式,然後弄個 proxy 實際看一下傳了什麼,不是很認真的研究。

話說我弄 proxy 的時候搞半天沒攔到東西,讓 cursor 一出手就搞定了,直接幫我把 asar 弄出來、patch 完然後塞回去,順便重新 sign 了一下 app,真的厲害,佩服佩服。雖然我自己弄也搞得定,但是出一張嘴就有人幫我辦事再好不過了。

AI 搶先找出漏洞

快速分享個昨天在推特上看到的有趣小專案

有個資安研究員 Eugene Lim 做了「Vulnerability-spoiler-alert」,原理是去掃幾個固定的開源專案,用 AI 去看最新的 commit 是不是在修漏洞,是的話反推回漏洞以及寫個 PoC。

由於一定是先發 commit 修完漏洞,然後才發版,所以如果有掃到的話,可以在發版前或是 CVE 公布前就先知道漏洞,因此作者把它稱為「Negative-Days」(但其實就算是一種 0 day 啦,不過稱為 negative day 確實也滿有趣的)

原始碼、相關文章以及網站本身都是公開的,最新的戰績是在 Grafana 提前找到了兩個那時尚未公開的漏洞:CVE-2025-41117 (XSS) and CVE-2026-21722 (Privesc)

雖然一定會有一些 false positive,但看起來成本應該沒有很高,而且達到的效益滿不錯的。

補充文章:https://vulnerabilityspoileralert.com/

AI 自主社群的疑問

其實我一直很疑惑為什麼許多人這麼相信 moltbook 是「完全由 AI 自主發起討論」的社群。

Moltbook 就是個平台,提供了一個 markdown 檔案說明該如何使用,你把 markdown 貼給 AI,AI 讀完之後讓你幫忙驗證,驗證完發一個 token,然後 AI 就可以用這 token 去 Moltbook 發文。

那…有什麼能阻止我自己用這個 token 假裝是機器人發文?或是,我難道不行跟我的 AI 講話,叫他去發個要毀滅人類的文嗎?發文就是拿 token 呼叫 API,真人做得到,AI 也做得到。

也就是說,我們其實沒辦法知道那些文章是 AI 「自主」發的,還是人叫他發的,或甚至是人假裝 AI 發的,這一點都不黑鏡。

我自己覺得最黑鏡的一刻是約一年前,我意識到「現在」就已經能做到黑鏡演出的科技。黑鏡有一集講親人過世之後用 AI 模擬聲音、講話內容等等,製造出一個分身,這個現在應該就做得到了?模擬聲音絕對可以,講話內容的話,拿各種本人資料喂給 AI 感覺也行,資料越多越逼真,看起來更像真的記憶?

如果要講 AI 發文,比起 AI 自己建一個社群討論,我覺得那些利用 AI 技術潛藏在人類中不被發現的魔族才更厲害,而且這已經是現在進行式了。你在追蹤的粉專或是網紅,也不一定是個真人,AI 發文、AI 回覆、AI 產圖,誰知道呢。

就算原本是真人,也可能在某個時間點主動讓 AI 奪舍,「可以用 AI 發文好方便欸,我就不用自己寫了」,儘管讀者不一定喜歡,但會在意的人又有多少呢?

既然都講 Moltbook 了,順便來講一下 OpenClaw(前 Moltbot 前前 Clawdbot),先承認我沒裝,我沒用過,所以底下都是一個沒用過的人打嘴炮,沒有參考價值。

我自己覺得 OpenClaw 成功的地方在於展示了一個真正的 AI 助理可能會長怎樣,因為它有整台機器的控制權,所以工具寫得好的話,想幹嘛就幹嘛,好像真的有個秘書在那邊一樣,而且記憶那塊好像也做得不錯。

但當然,你得付出的是一些安全性的代價,越方便的東西往往越不安全,我建議不管你用什麼環境架它,都要有個心理準備:「你整個環境都會是開放的,是會被駭的」,在這個前提底下去使用它。

所以你可能不會想把信用卡號放上面,給他的 AI token 也會設好使用上限,不會給他郵件的帳號密碼,只會用它來做一些就算資料被偷也沒什麼損失的事情。不過在這種前提下,可能方便度就減少很多了。

話說,虛實整合這一段我倒是滿感興趣的,我有看到那個什麼它的小龍蝦訂位失敗所以自己打電話的故事,但真實性存疑就是了,仔細看應該是事主自己額外又教了 AI 怎麼打電話,而不是 AI 主動學習。

當有服務提供 API 讓人打電話跟接電話時,接入 AI 就可以把虛擬接入現實,客人用 AI 幫忙打電話預約,商家用 AI 幫忙接電話,自動把訂位接入系統。(不對啊,你用 AI 我也用 AI,那幹嘛不網路訂位就好或乾脆餐廳提供個 API,幹嘛還要過一層電話。應該是個過渡期,給那些只會用電話的人)

話說這些其實也是現在進行式了,早就有人在做了,只是我還沒研究過台灣有沒有能夠打電話 + 聽語音的 API。

寫了這麼多,總而言之呢,我自己認為 OpenClaw 是個成功的產品而且滿有趣的,但我自己暫時不會想用(懶惰且沒這需求,我也懶得因為要寫貼文去用),而 Moltbook 在我沒理由相信真的是 AI 全自主發文的前提之下,更是一點興趣也沒有。

Closure 記憶體陷阱

今天 Bun 的作者 Jarred Sumner 在推特上發了個文,説對於跑很久的 Claude code session 來說,底下的改動可以省掉 1GB 的記憶體:

Before: => controller.abort
After:controller.abort.bind(controller)

從原本的 function 換成了 bind 的用法,為什麼這樣就可以呢?或是換個方式問,為什麼原本的寫法會吃比較多記憶體?

在原文附圖的註解裡就有寫原因了,說原本用 closure 的寫法,會把整個 scope 記住,而這個 scope 有 request body 跟其他大的物件,所以在結束以前,這些被包住的東西都沒辦法被 GC,就會一直佔空間。

而修改後的做法沒有 closure 了,所以不會記住那些無關的東西。

這個問題其實在我的書《JavaScript 重修就好》裡面就有提過了,有書的同學可以打開翻到 4-44,講 closure 可能造成的潛在問題,我給了這樣的案例:

function createWebSocketHandler {
  let socket = new WebSocket("wss://example.com/chat");
  let messages = [];
  socket.onmessage = function(event) {
    messages.push(event.data);
  };
  return {
    sendMessage: function(text) {
      socket.send(text);
    },
    closeConnection: function {
      socket.close;
      socket.onmessage = null;
      socket = null;
    }
  };
}
const chatHandler = createWebSocketHandler;
chatHandler.sendMessage("Hello, world!");
chatHandler.closeConnection;

在關閉連線時,我們將 socket close,然後把有用到 messages 的 onmessage 清掉,也把 socket 整個清掉,看起來沒人用到 messages 了,就想說安全,既然沒人用到那就可以被 GC 了。

但這是在使用 closure 時會產生的錯覺,那就是「只有我有用到的東西才會被記住」。事實上,closure 才沒有在管你使用與否,只要是同一個 scope 的東西就全部記了下來。

因此,儘管 sendMessage 與 closeConnection 這兩個函式沒有用到 messages, 它依然被引用了。所以就算把 socket.onmessage 給清除,messages 的記憶體空間還是沒辦法被回收。

重點只有一個,就是 closure 是整個 scope 都會記著,被記住的東西就不會被 GC 了。這恰巧也是 Claude code 碰到的問題,沒有察覺到那個被回傳的 function 會記住整個 scope。

然後這也跟 AI 寫 code 一點關係都沒有,一堆人類也會寫出這樣的 code,況且現在人跟 AI 誰寫得比較好還很難說呢,尤其是對那些非工程師來說。

這個案例是人是 AI 都有可能犯錯,但如果是其他案例,當有人責怪 AI 怎麼寫出這種爛 code 的時候,AI 說不定會想跳出來抱怨:「我才不會犯這種錯呢,這一定是人類寫的」。

補充文章:https://x.com/jarredsumner/status/2017825694731145388

滑板車預設金鑰漏洞

今天看到篇有趣的文章,來自愛沙尼亞的資安研究員 Rasmus Moorats,標題是:《Reverse engineering my cloud-connected e-scooter and finding the master key to unlock all scooters》,逆向工程我的電動滑板車,卻不小心找到了可以解鎖所有車車的 master key。

這位研究員他有一台 Äike 出的電動滑板車,但這間公司去年破產了,而電動滑板車附帶的 app 有些功能也跟著停用,雖然還是能夠解鎖,但由於這個 app 都是連到某個 server 去,他很擔心哪天這個 server 直接關掉,就可能再也用不了。

於是作者開始逆向這個 app,想看一下背後的原理,發現手機跟電動滑板車的溝通是透過藍芽以及自訂的傳輸格式,在一開始的身份驗證流程中,會先從車車那裡拿到一串字(給一個 challenge),要能產生正確的回答才會成功。

作者觀察一下發現這個回答有點像 SHA-1,於是就 hook 了一下,發現還真的是,先從車車那裡讀到一個字串,把字串跟 private key 拼在一起丟去 SHA-1 再送回去,就可以完成身份認證。

那這個 private key 是什麼呢?答案是 20 個 FF。

為什麼是 20 個 FF 呢?因為這是某個 IoT SDK 的預設值,只要沒有改的話,你預設的 private key 就是這個。

而 Äike 的開發人員可能是忘了改,每台車用的都是同一個 private key,都是同一組。因此呢,作者不只能解鎖自己的車,也能順便解鎖其他人的。

作者後來也把整組溝通協定都逆向出來了,寫了一個自己的 app 來控制他的電動滑板車,甚至可以透過智慧手錶來控制,做到以前做不到的事情,這就是逆向的厲害之處(?)

這種「沒改預設 key」其實也不少見,有些可以自己架的網站也會這樣,或甚至有些直接 hardcode 一個 secret key,這也一直在發生。

正確做法是每一次安裝都隨機產生一個 secret key 幫你存起來,而這個電動滑板車的案例,應該每一台的 key 都要不同才對,而且要是不可預測的。

原文有附更多技術細節,包含 Frida 的腳本以及如何逆向新版 React Native(看到這篇我才知道原來新版變成 bytecode 了,我的知識還停留在整包 JavaScript 的時代)。

補充文章:https://blog.nns.ee/2026/01/06/aike-ble/

AI 熱潮背後的代價

我不會否認 AI 很厲害,但我也不會一直無腦吹 AI,彷彿每一次的更新都會改變世界,每個新功能都重塑了整個產業。

比起分享 AI 的新功能又可以做哪些事情,我更喜歡分享那些只會一味吹捧的人沒去關心的後續,或是 AI 在增加生產力的同時,是如何同時造成另外一群人的負擔。

其一

Cursor 前幾天說他們在測試一堆 AI agent 全自動化能做到什麼地步,最後弄出了個瀏覽器,程式碼足足有 300 萬行以上,而且最重要的 rendering 引擎是從零開始的,原話是:

The rendering engine is from-scratch in Rust with HTML parsing, CSS cascade, layout, text shaping, paint, and a custom JS VM.

聽起來就超級猛,居然可以直接從零弄一套瀏覽器出來。

但沒多久就有人質疑這些所謂的「從零開始」其實依賴了很多現成套件,HTML parser、CSS parser 以及 JavaScript 引擎等等,都只是現有套件再往上包一層。

而 Cursor 的人也有出來回應,說確實有些地方用了套件,但他們覺得 agent 自己其實也做得出來,這個實驗性質的專案之後會慢慢遷移這些。

但總之,看來 Cursor 的「from-scratch」定義似乎跟想像中不一樣。我認知的 「from-scratch」也是從頭自己刻,就算依賴套件也不會到這種程度。

同我開頭所述,我很喜歡 Cursor 這些實驗性的專案,讓人可以窺探目前 AI coding 的上限大概到哪裡,成果很厲害沒錯,但稍嫌誇大了。就算沒這麼誇大,只說是把現有套件整合弄出個瀏覽器,我也會覺得很厲害的。

其二

拿來畫圖很好用的開源套件 tldraw 日前宣佈不再接受來自外部的 Pull Requets 了,理由是太多 AI 垃圾(AI slop),發了 PR 就跑,也不討論不改東西,原本提的東西可能也沒測過,就這樣發上來了。

這種 AI 垃圾一多讓維護者身心俱疲,畢竟每個垃圾都是一種雜訊,光是要篩選出哪些是真的可以用的,本身就是一個成本。

但作者有強調這是暫時的,之後 GitHub 似乎會上新功能來解決這問題,我猜可能是用魔法對付魔法,先弄個自動 AI 分類?或可能有辦法識別出這種 AI 帳號,或是某個帳號提出的 PR 品質之類的。

總之,到時候推出了再來寫一篇吧。

其三

同上,一直被 AI 垃圾深深困擾的 cURL 正式停止了 bug bounty program,理由是:

We have concluded the hard way that a bug bounty gives people too strong incentives to find and make up “problems” in bad faith that cause overload and
abuse.
漏洞懸賞計畫給了人們過於強烈的誘因,導致有人出於惡意,去尋找,甚至捏造所謂的「問題」,從而造成負擔過重與濫用。

簡單來講就是一堆 AI 仔隨便讓 AI 找些問題,自動寫報告交出去,自己也沒驗過(搞不好也不知道怎麼驗),讓維護者們收到一堆垃圾,心力交瘁。之前 cURL 就寫過這問題了,現在正式靠著把賞金拿掉,希望減少一點誘因。

AI 時代很多東西的成本變低,濫用也變得更加嚴重,我可以想像得到有些人寫個 AI agent 自動掃描所有 bug bounty target,自動找一些簡單的洞,自動寫報告然後送出。

是不是 false positive 不重要,反正有人會幫我驗,100 個裡面成功 1 個我就有錢拿,驗證的成本轉嫁到別人身上,錢是我在賺,好爽。

以上是三個,最近看到的與 AI 相關的新聞。AI 很厲害,很好用,我自己也很常用,但它絕對不是百利而無一害,這樣的方便性也造成另外一群人的困擾。

有許多人都還在找尋與 AI 共存的方式,我也還在找。看到臉書一堆 AI 垃圾也增加了我篩選的負擔,我通常看一個封鎖一個,還想過要不要自己寫一個貼文收集工具,AI 先幫我過濾一輪(但我懶,只是想想而已,我知道有類似工具,但我也懶得去用,結論是我就懶)。

,有興趣的可以看一下。

參考資料:https://x.com/wilsonzlin/status/2012404100298871048

Tailwind 營收下滑

差點忘記要來寫 Tailwind CSS 了。已經是幾天前的事了,應該不少人都有看到,但我還是稍微前情提要一下。

有個叫做 Tailwind CSS 的開源專案,由於 AI 的大量採用變得越來越多人使用,但是背後的公司 Tailwind Labs 的付費產品資訊是放在官方文件裡面的,現在大家都用 AI 寫 code 沒人看文件,導致流量大幅下降,營收掉了 80%,工程團隊裁了 75% 的員工。用的人變多,營收卻變少,看起來是件滿弔詭的事情。

但從我自己的觀點看,這並不是什麼新鮮事,在 AI 風行以前其實就這樣了,甚至對有些專案來說還更糟。

要解釋這個說法,我們要從頭開始看,先回答兩個問題:「Tailwind CSS 是什麼」以及「Tailwind Labs 的付費產品是什麼」。

Tailwind CSS 這東西在 2022 年的時候就已經在前端圈很紅了,那時 ChatGPT 都還沒出來。關於技術面以及歷史的探討,我當時就寫過一篇《淺談 Atomic CSS 的發展背景與 Tailwind CSS》。一言以蔽之,Tailwind CSS 是個實作「Atomic CSS」這個概念的 library。

「Atomic CSS」的概念從 2013 就存在了,是起源於 Yahoo! 的工程師 Thierry Koblentz,這個概念打破傳統 HTML 與 CSS 分開寫的最佳實踐,用實際案例說明 HTML 跟 CSS 寫在一起會更好。儘管這個概念在現代已經變成顯學,更是 AI 預設就會寫出來的東西,但是在約 2022 年之前,這其實被大部分工程師視為「邪魔歪道」,許多人聽到會覺得「你在跟我開玩笑嗎?這樣寫哪裡好?」。

太技術面的我們不談,可以簡單想成原本大家都是寫

跟 .block { color:red; },兩個分開的,但是 Atomic CSS 的概念告訴我們要寫成
,用 class 名稱直接表示樣式。

只要符合這個概念都叫做 Atomic CSS,就想成是個流派吧,而 Tailwind CSS 就是基於這個流派開發出來的 library。Tailwind CSS 並不是第一個,它是 2017 年出現的,還有其他更早的如 Atomizer 或是 Tachyons,都是基於同一個概念,所以用法其實都大同小異。

那這樣的一個 library,要怎麼賺錢呢?

Tailwind Labs 的主力產品是一個叫 Tailwind Plus 的產品,簡單來講就是一堆寫好的模板。無論是小的 component 或是可以直接拿來改的 template,都幫你準備好,買了以後你可以直接套用,節省開發時間。

價錢的話個人是美金 299 元,公司是美金 979 元,一次購買終身使用,這些模板會不斷更新。

這東西我很早就知道了(AI 出來之前),那時候的想法是:「原來現在這種模式還可行」,畢竟這種賣網站模板的,感覺應該是更久以前的商業模式,很像那種買一個電商網站或是遊戲,改一改之後你就可以變成自己的產品。

我可以理解某些公司可能需要,但沒想到這麼多,所以覺得他們滿厲害的。當時這產品的營收滿高的所以我很驚訝,剛剛查了一下,作者在 2020 年的時候有發文,說上線後的 5 個月內,營收是 200 萬美金,約 6000 萬台幣。

回答完「Tailwind CSS 是什麼」以及「Tailwind Labs 的付費產品是什麼」之後,我們再回頭來看這次事件。

首先,裁員 75% 指的是 3 個人,因為工程團隊本來就只有 4 個人,所以只剩創辦人一個。

再者,雖然營收下滑的理由被描述為「因為付費產品資訊只在文件上曝光,沒人看文件就沒人知道」,但我自己覺得主因更有可能是 AI 時代不需要這些了。

現在你如果想做 UI,直接 AI 起手給他一兩句話就幫你寫完,我想不太到需要那些模板的理由(就算要買,現在可能也是喂給 AI 而不是人看了)。換個方式問好了,現在大家知道了 Tailwind Plus 這個模板套裝組合,想購買的意願有多少?預估能節省到的開發時間又有多少?

因此,我自己會覺得 AI 的演進,本來就會使得這種賣模板或是程式碼的商業模式受到打擊,跟文件以及流量的關係可能沒這麼大。以前不會寫 code 的人或許會花錢買網站找人改,現在都自己用 AI 寫一個了。

而「東西越來越多人用,作者卻沒有獲得更多營收」這件事原本就一直都是開源生態必須面臨的挑戰,在沒有 AI 之前就是這樣了。甚至有更多時候是「作者根本沒有任何營收」,大部分開源專案都是用愛發電,作者沒有得到任何實質收入,就算有贊助功能,會贊助的人本來就偏少。

如 2019 的時候 core-js 作者在 postinstall 放捐款連結跟求職資訊,或是 2021 年 Parcel 也做了類似的事情,都是因為資金碰到一些困難因此不得不做。而目前又可以做開源專案又可以賺錢的方式,大概就兩種最多。

第一種是公司養你,你做開源。當公司大到一定程度,可能會專門找人來維護這些開源套件(畢竟自己也要用),或反過來,很多開源專案本來就都是大公司釋出的,所以內部有人專門在做這些。也有些公司直接把開源專案買走,如前陣子 Vercel 收購了 Nuxt,Anthropic 收購了 Bun,都是類似的。

第二種是開源的同時,也提供 SaaS 服務。如 GitLab 或是 WordPress,你可以完全免費自己架,也可以直接花錢跟他們買服務,只要用就好,其他都交給他們處理(話說我不太確定這兩個是先有開源專案才商業化,還是反過來。雖然結果一樣但有細微差別,不過這邊先不多談)。

但第二種可行的前提在於,這個開源專案必須是一個產品。那既然是產品,就必須產生這個產品該有的價值。我覺得 Tailwind CSS 很難走這條是因為,比起產品它更像個單一的 library,而且可取代性高,還記得我前面提過的那一堆 library 嗎?用法都很像的,畢竟都是遵從同個派系的教條,換一個需要的成本並不高。

總之呢,有些 library 走出了自己的路,如 React Router 一開始是透過提供 training,後來被 Shopify 買走(Remix 被買走,但都是同一套)。而 Vue.js 則是光靠企業與個人贊助就可以生存。但前提都是一樣的,就是這個產品有價值。

那 Tailwind CSS 有沒有這個價值呢?

有的,當這個裁員消息一出來之後,這幾天就有許多公司跑去贊助 Tailwind CSS 了。

不知不覺寫了好多,好像寫篇部落格會更好 😂

總之呢,我想表達的是,這整件事情的本質跟以前沒有不同,它一直在發生,不是什麼新鮮事。甚至更多的狀況下,作者一點營收都沒有,純粹用愛發電。而 Tailwind CSS 雖然找到了一種營利的模式,但這模式在 AI 時代下本來就會遭受打擊,與文件或流量的關係不大(我覺得啦)。

所以應該解決的問題還是一樣的,那就是開源與商業的共存,跟 AI 關係可能沒這麼大?這件事會跟 AI 有關,我覺得也只是因為剛好他們的商業模式受到 AI 衝擊的力度很大。

補充文章:https://adams-morning-walk.transistor.fm/episodes/we-had-six-months-left

AI 時代的真實焦慮

之前一直沒有寫篇文章聊聊我對 AI 的感想,主因是時間太早,變化太快,寫完之後隔一年用起來的感想就都不一樣了。

但最近至少在 coding 這塊看起來比較穩定了(我指的是,AI coding 已經是必然,回不去了),是個較為適當的時機。

文中講的內容不一定與 coding 有關,而且更多的是對 AI 發展後的一些擔憂,我在這邊簡單提一下好了,

第一個是時間與誠意,以往我們可能會用做某件事需要花費的時間推導出誠意,畢竟時間具有排他性以及稀缺性,在只能本人做的前提下,願意花時間其實是件很珍貴的事情。

但我們不會知道他到底花多少時間,只能從產出推估。AI 出現前,看到一篇文情並茂的 3000 字文章,可以想像背後大概花了幾個小時。但現在呢?有可能只是花三分鐘用 AI 寫的,原本的衡量標準失效了(不要覺得你一定看得出來某篇文章是 AI 寫的,就算現在可以,不遠的將來肯定也看不出來了,「AI 味」會慢慢消失)。

雖然時間少不一定代表沒有誠意,這我知道也可以理解。但仔細想想,有些事情還是得用時間來衡量對吧,那這些該怎麼辦呢?

第二個是 70 分的詛咒,當 AI 花 3 分鐘就可以做出 70 分的東西,那誰還會多花 300 分鐘去追求 80 分呢?

AI 快速做出可用的東西無人能敵,但要繼續在產品上進步需要人介入調整,告訴他哪些細節可以改進,這塊可能要花更多時間。在 AI 出現前,光是做到 70 分可能就要 300 分鐘或甚至更久,現在比例不同了,那這是否會成為追求 80 分的阻礙?

還是說想做到 80 分的人,不管怎樣都會做到 80 分,那些會止步於 70 分的人原本就會止步,其實是兩群人?

第三個是真實性越來越難判別。

無論出自於什麼目的,是純粹樂子人還是政治因素,假消息一直都存在。但 AI 讓造假的成本變得很低,以往我們可能會看某個帳號的過往紀錄,這個有本人照片、一直發貼文、以前 po 過很多言之有物的文章,所以像是真人。

但現在一堆 AI 人出現在各地,要照片有照片,有多真就多真,你根本不知道背後是個真人還是 AI。

有些人根本不在意是不是 AI,反正只要最後寫出來的東西合他胃口就行,是真是假根本不重要,重點是那個故事本身想傳達的東西。

但我沒辦法,我在意真實性,我在意某件事情是不是有真實發生過。就算是一個我認同的概念,只要搭配虛構的故事,我就不會買單。但判斷真實性這件事情變得越來越困難,我只能逐漸轉向「預設任何事都是假的」這個立場。

除非有經過可信任的第三方證實、證據夠明確或者是我信任的朋友所述說的事情,否則我都一概先認為那是網路假文章,而且不會轉傳。

造謠一張嘴,闢謠跑斷腿。最近的外送演算法也好,前陣子的 Slack 資料放中國也好,在得到足夠的資訊外加各方說法之前,我只會默默觀望,不會為了流量搶快就先分享再說。

我對 AI 還是又愛又恨的。

AI 在許多領域帶來的改變,說穿了就是讓生產力大幅提高,而且是以十倍百倍那樣子的速度。這個工具可以運用在好的地方,也可以運用在壞的地方。

當我原本就看不慣的東西,因為 AI 而變得更猖狂時,我就更看不慣了。例如說內容農場、AI 文、AI 假帳號或是透過 AI 販賣焦慮等等,AI 讓這些垃圾的產出變得更容易。但與此同時,我自己用 AI 翻譯部落格,用 AI 在工作上寫 code,平常查資料也是先問 AI,整理資料也是 AI 幫忙,也是著實的 AI 受益者。

AI 的進化能夠讓人反思自己在意的價值觀到底是什麼,要堅守哪些,又要犧牲哪些,需要找到一個能與它和平共處的方式,這個我還在努力。

MongoBleed 漏洞解析

有讀者私訊想看我寫上周爆的 MongoDB 漏洞 MongoBleed(正式編號為 CVE-2025-14847),之前其實就有關注到只是沒仔細看,看了一下發現這個名字取得不錯。

取 MongoBleed 這名字的人,參考的是 2014 年的 TLS 大漏洞 Heartbleed,這兩個漏洞的成因都滿類似的。Heartbeat 俗稱為心跳,是一個常見的網路機制,通常用於確認跟你連線的對象是不是還活著,常常都是固定每幾秒發一個封包過去,有東西回來就代表對方活著,形象一點可以想成心電圖那樣,每幾秒就一個波峰,就像心跳那樣,每幾秒跳一下。

而 Heartbleed 這漏洞是 TLS 中對於心跳機制的實作有問題,在心跳的封包裡面可以傳 payload 跟 payload 的 length,server 端應該要把 payload 原封不動回傳。

在正常狀況下,假設 payload 是 hello,payload length 是 5,server 就回傳 hello。但如果 payload 不變,payload length 改成 1005 呢?server 就會回傳 hello 外加 1000 個在記憶體裡面的隨機字元!

由於 server 直接相信了 payload length,因此多出來的這些地方都會是 server 記憶體的其他內容,有可能是剛解密的 request,或甚至是 server 使用的 private key 等等,每傳一個封包就洩漏出隨機的字串,資料像是流血那樣一點一點不斷流出,就成了 heartbleed。

這次的 MongoBleed 也很像,是 zlib 的壓縮功能有問題,一樣可以傳 payload 跟 length,而且 length 同樣沒檢查。於是我宣稱自己的 payload 有 1005 個字但實際只有 5 個,後面 1000 個字元就會是 memory 的隨機內容,再搭配 MongoDB 在解析 JSON 時的報錯,就可以從 response 的錯誤訊息中得到 memory 的內容。

雖然每次拿到的內容都是隨機的,但只要一直發請求就會一直拿到新的東西,如同我前面提的,像是出血那樣,一點一點流血,資料也一點一滴流出。

再者,MongoBleed 之所以嚴重,是因為這個功能是在 auth 之前的,根本不用登入就能打。所以只要你的 MongoDB 開放在外網就會被打,就算你帳號密碼強度超強也一樣,只要外網連得到就是被打。

下次有人跟你說:「資料庫直接對外沒差啦,我們有設帳號密碼啊而且強度很強」,你就丟 MongoBleed 這個漏洞到他臉上,讓他看看資料庫 public 的下場。

參考資料:

Email 比對與帳號接管

之前在 conf 講過的案例中,有一個滿值得特別拿出來講。

假設有個忘記密碼的功能,使用者輸入了 email,接著你拿去 DB 查,用了 select * from users where email = ?,去查有沒有這個 user,查到了之後直接拿使用者輸入的 email 寄重設密碼信給他,會有什麼問題?

答案是使用者輸入的 email 跟 DB 裡存的 email 不一定是相等的。

舉個最簡單的例子是大小寫,MySQL 有些 collation 是不區分大小寫的,所以 gmail 跟 GMAIL 相等,這倒是問題不大。

但在有些 collation 中,gmail 跟 gmaîĺ 是相等的,也就是說使用者輸入的是 huli@gmaîĺ,DB 查到了 huli@gmail 這個 user,但最後寄信給huli@gmaîĺ,而 gmaîĺ 這個網域是買得到也寄得到的,於是你的系統就把重設密碼信寄給了錯的人,出了一個 account takeover 的漏洞。

最早看到這個是在今年 6 月份 Voorivex 發的文章:Puny-Code, 0-Click Account Takeover,不確定更早有沒有人提過。

目前看來 PostgreSQL 基本上沒這問題,但 MySQL 的話你選常用的 utf8mb4_unicode_ci 或是 utf8mb4_general_ci 都有這問題。與其說是問題,不如說是 feature 就是這樣,只是很多人不知道有這 feature 而已 😅

至於修法的話,就是不要相信 user input 就對了,要寄信的時候拿 DB 查出來的 email 寄信,就不會有這問題。在實作上應該大部分都是拿 DB 內的 email 寄信啦,不過拿 user input 寄的其實也不少,畢竟你會覺得他們相等嘛,用哪個都一樣(並沒有)。

補充文章:https://dev.mysql.com/doc/refman/8.4/en/charset-collation-implementations.html

Vercel WAF 賞金大戰

話說有關 React2Shell 的那個漏洞,Next.js 背後的公司 Vercel 第一時間就上了 WAF,讓客戶在還來不及升級時,先幫他們擋著惡意攻擊,這是很常見的做法。

但 WAF 要做好是很難的,因此在推特上就漸漸有人找出 bypass 的方法。

而接下來 Vercel 做了件瘋狂的事情,為了表達他們對這個漏洞的重視程度,他們特別開了一個 bug bounty program 給 WAF bypass,而且獎金高達 5 萬美金!每找到一個繞過 WAF 的方法,就有 150 萬台幣可以拿!

而今天這個 program 正式告一段落,那些回報的 WAF bypass 都被修掉了,最後總共發出 85 萬美金(約 2500 萬台幣)的獎金,那些武功高強動作又快的白帽駭客們成了最大贏家。

拿到賞金的駭客有些我們以前也介紹過,如前陣子發現 Unity launcher 漏洞的 ryotak,或是最早釋出 1-day exploit 的 maple,以及打了很多個 AI 瀏覽器,在做 AI 輔助工具的 hacktron,這些都在榜上。

我以為只有幣圈會拿這麼多錢出來給 bug bounty,沒想到 Vercel 這次也這麼慷慨。

React 後續漏洞修補

React 剛剛又發布兩個跟上週有關的漏洞囉,但這次一個是 DoS 另一個是特定情境下可以洩漏 server function 的 source code,嚴重程度都遠低於之前的 React2Shell,編號如下:

  • Denial of Service (High): CVE-2025-55184
  • Source Code Exposure (Medium): CVE-2025-55183

然後 Next.js 也理所當然地受到影響,因此也推了一版 patch。

雖然說沒之前這麼嚴重,但有時間的話還是建議先修一修。話說 React 發布這個漏洞的部落格寫說:「It’s common for critical CVEs to uncover follow‑up vulnerabilities. 」,說這種嚴重的 CVE 公佈之後,可能會有更多類似的漏洞這很正常,拉了 Log4Shell 當作案例來解說。

是這樣沒錯,但好像又不是這樣(?)

我以為像 Meta 這種大公司,收到第一個 report 之後會找 security team 進來整個看一遍,把其他潛在該修的問題都修一修再上 patch,但看起來整個反序列化的機制一樣有問題,才出現這兩個洞。應該是我對這種大公司有什麼誤解,看來也是見一個修一個。

不過往好處想,現在一堆資安研究員都往這邊看了,看了一週後才出現這兩個漏洞,代表應該還算安全 😅

建議最近這一兩週還是密切關注一下 React 的新消息,有可能還會有更多小的漏洞出現。

React 漏洞利用鏈解析

看了某個中文講解 React 漏洞 CVE-2025-55182 的影片,看完只覺得他是不是根本沒有看懂整個漏洞在幹嘛 😅 (不想給流量,不會貼網址)

最重要的 constructor.constructor 直接被跳過了,講的好像 server 原本就來者不拒可以執行任意程式碼一樣,重點也完全不是什麼隨便相信外面的東西,這本來就是一個反序列化的 protocol…,你看最後的 patch 就知道成因根本不是那樣了

看得出來是直接從最後的 exploit 往回倒推在哪裡執行的,但卻根本沒看懂整個利用鏈,直接倒果為因,明明就有很多文章可以參考 😢

完整的利用鏈我還沒看,但我目前的理解是,React server 那邊有個反序列化的 protocol 支援一些 reference 的操作,例如說你可以把 $1 定義成 {“name”:”huli”},接著用 “$1:name” 就可以表示 obj.name 這個概念,在反序列化的時候變成 “huli”。

這樣的操作可能是為了做資料壓縮?可以用 reference 的方式去取得那些資料,有點資料正規化的感覺。所以正常使用下,我猜整包反序列化完以後應該還是個 JSON 物件

然而,在取值的時候沒有檢查 key 是不是在那個 object 上,因此你隨便定義一個 string,拿這個 string 的 constructor.constructor,就可以拿到 function constructor,這次 bug 的根因是這個。

接下來只要想辦法把參數傳進去然後執行,就可以執行任意程式碼了。而這一步應該是整個利用鏈最難的,儘管已經知道上面這些資訊,資安專家們還是花了半天到一天的時間才找到該怎麼利用這點(kudos to maple <(_ _)>)。

這段也是我還沒仔細看的部分,要花滿多時間理解的。但總之看起來是利用原本解析流程的一些邏輯,做出一個假的 chunk,而這個假 chunk 被丟下去解析完以後,最後會呼叫 response._formData.get(response._prefix + obj)

所以我們可以用前面提過的方式,把 response._formData.get 變成 function constructor,然後在 _prefix 裡面放程式碼,就會得到一個我們要的 function,然後丟到 { then } 裡面會因為 Promise 的特性被自動執行,流程應該是這樣,只是細節可能不太對。

最後的 patch 我記得是加個 hasOwnProperty 的檢查,確保在呼叫 obj[key] 的時候,那個 key 是真的存在於物件上的,就不會拿到奇怪的東西。

看完上面,你就會知道跟那個影片講的完完全全不一樣。

然後 SSR 跟 RSC 原本就是兩回事,雖然這概念確實滿容易混淆的,但寫前端的應該要知道他們的區別。

儘管我自己到現在也還是不喜歡 RSC(對我來說成本太高,效益太低),也早就沒寫 Next.js,甚至也很少寫 React 跳去 Vue 了,但看到有人在轉發的影片傳播部分錯誤資訊,還是想出來講一下。

React RSC 嚴重漏洞

一早醒來就看到 React server components 爆了個嚴重漏洞 CVE-2025-55182,給了滿分 10 分,官方描述是:There is an unauthenticated remote code execution vulnerability in React Server Components.

說是 RSC 的實作上有個 unauth 的 RCE,只要發個請求到 server 就能打下來,是最嚴重的那種。

而有用到 RSC 的下游都連帶受到影響,例如說 Next.js 也迅速標了個 CVE-2025-66478 然後出了 patch,目前在描述中也沒有給太多資訊。

現在駭客們正在想辦法從 patch 反推回 PoC,應該很快就會出來了(原始 RSC 的已經有部分了,但是 Next.js 的還沒看到),雖然看起來攻擊有些前提,但目前是謠傳你用預設設定也會出事,有不少資安公司也都發了初步公告了。

總之呢,有用到 Next.js 的都建議盡快升級修掉。等有人分享出完整 PoC 跟技術分析之後,再來寫一篇談談吧。

Pixnapping 側信道攻擊

前陣子看到一個叫做 Pixnapping 的攻擊方式滿有趣的,是一種針對 Android 硬體的 side channel attack。

在理解什麼是 Pixnapping 之前,先來看另一個兩年前就被公佈的攻擊方式 GPU zip。GPU 在渲染畫面的時候會做壓縮,所以在網頁上你可以用 iframe 把要攻擊的網站嵌入進來,然後利用一些 CSS 去改變它的顏色或是特別調整某個區塊。

舉例來說,可以用 CSS 獨立出某一個 pixel 然後放到很大,接著疊上一些隨機產生的點,如果畫面是白色就會難以壓縮,若畫面是黑色壓縮率就很好(背後跟 GPU 怎麼壓縮東西有關,總之結論是這樣)

再搭配 render 時間的測量,就可以反推回去原始的某個 pixel 是黑是白,重複這樣的操作就能 leak 出原本的畫面大概長什麼樣子。

而這個 Pixnapping 就是在 Android 上利用 App 可以 overlay 在別的 App 上的特性,先把 Authenticator App 開在後面,上面疊加自己的 App,然後自己的 App 變成半透明去改變顏色,就能利用類似手法,洩漏出底下 App 的某個 pixel 是黑是白。

簡單來講呢,最終結果等於是你可以對其他 App 做個 screenshot (只是需要點時間)。

針對 GPU 進行資料壓縮的特性來做 side channel attack,推斷出 pixel 顏色,進而推斷出畫面,就可以拿到上面的資料,滿有趣的。