隨意聊

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

共 110 篇 第 1 / 6 頁 RSS 訂閱

置身钉内盜版烏龍

今天來跟讀者們道個歉,順便分享我怎麼被網路盜版文章騙到。

前天我分享了幾篇文章給大家,其中有一篇是滕雅辛的《置身钉内》。但我後來又重新找了一下資料,發現那篇是錯的,而且很有可能是 AI 改造過的版本。

就讓我從頭開始分享一下我的心路歷程。

其實上週就開始在推特看到《置身钉内》的相關消息了,雖然很有興趣(七萬五千字,我最愛看長文了),但是一直拖延症還沒點進去看。直到前幾天終於提起動力去找,就在 Google 上搜尋了。

搜尋的結果,第一名是知乎上的「阿里内网7.5万言离职书《置身钉内》原文,已刷屏」,第二名是百度百科,然後我一直記得之前在推特上看過 PDF 版本的,找到了一個知乎上的「钉钉内网幽素7万字长文《置身钉内》(2026转载)」,裡面是 PDF 的截圖。

由於這些都不是很好讀,於是我忘記是從 Google 還是從推特上看到有人弄成 markdown 搬到 gist 去,就從 gist 版本開始看。在看的時候我還有先對照兩版是否一樣(因為 gist 上沒有圖,另一版有圖,也想順便看一下原本的圖片是什麼),發現前幾段都一樣,就放心看下去了。

就這樣把 gist 給讀完,也花了一段時間,然後去看了高層回應的《置身钉外》,其實當初看的時候就覺得有一點奇怪,因為裡面提到:「幽素在文章结尾说,泰坦尼克号沉了,但船上的水手还可以找下一份工作。」,我想說我怎麼對這段沒印象,是不是漏看了,但也沒想太多。

直到後來要找其他資料,才突然發現我看的《置身钉内》是假的。

這個「盜版」的《置身钉内》,第一卷跟第二卷的前半段,跟原版是幾乎一模一樣的,但是從那之後就都不同了,之後的內容看起來相當具有 AI 特色,半總結半瞎掰,什麼:

「跳出ONE单一产品看行业,我在这一年最深的用户侧感悟:办公AI的第一底线:绝不强化管控,绝不放大内卷」

「所有人都在狂奔、所有人都在加班、所有人都在透支、所有人都很努力 ——唯独没有人在思考:我们奔跑的方向是不是错的。」

甚至是結尾的「过往踩过的弯路、犯过的错误,若能成为后来者的前车之鉴,便是这七万五千字长文存在的全部意义」,都是原文完全沒出現過的句子。裡面也有很多原文根本沒出現的內容,雖然皮骨有些許類似,但血肉是完全不同的。

所以我看了一個盜版還興沖沖的想跟大家分享,真滴丟臉。現在回想起來,當初在看這盜版時,確實越往後看越不對勁,怎麼好像越來越短跟摘要似的,但因為講得有些道理,再加上文章也確實長,就沒有想太多。後來統計了一下,這盜版大概兩萬多字而已,跟原版差得遠了。回去看原版以後發現,無論是在心得上或是文字上,都遠勝盜版太多,盜版確實無法比。

至於這盜版哪來的,我也不知道,我猜是某個營銷號為了搶流量用 AI 搞出來的,而且流傳很廣。前面提到的 Google 搜尋的結果,前兩名那個也都是盜版,百度百科上的也是,你拉到文章第八卷結尾,最後一段寫什麼「若能成为后来者的前车之鉴,便是这七万五千字长文存在的全部意义。」的就是盜版,正版第八卷以後還有東西,而且結尾厲害多了:

「我无法不写。太多思绪和文字,像胃里的蝴蝶,我一仰头,他们就忍不住从食管中争先恐后地飞涌出来,抛下云雾一样的翅粉,火山灰一样悠悠落回我的脸上,遮住我的视线。于是我才终于可以瞑目,安心地开启我的下一段旅程。」

為什麼我會這麼肯定前者是盜版呢,有沒有可能是更早的版本,或是還有分內部版跟外部版呢?我已經發揮追根究底的精神,直接在小紅書上面聯絡作者了,他說這個版本他沒寫過,所以是盜版沒錯。

以上就是關於《置身钉内》正版與盜版的故事,跟之前看到盜版的朋友說聲抱歉,之後我會更謹慎挑選文章來源。如果之前讀的是盜版,建議重讀一次正版,我相信會有更多感觸的。

近期好文推薦

來分享幾篇最近讀到滿喜歡的文章,只會大概講一下在寫什麼跟我的讀後感,不會幫你用 AI (自以為是的)濃縮成精華,因為整篇都是精華。

第一篇是芭樂人類學的《AI時代的(大學部)田野教學》

這篇在講在教學中(以人類學的田野實習課程為例)導入 AI 的過程,到底哪些東西可以交給 AI,哪些又不行?與其讓大家獨自探索這個標準,不如由整個課堂在老師以及助教的帶領下,共同建立一個守則。

文中有個 AI 光譜很有趣,把 AI 的使用分成 5 個 level,分別代表不同的介入程度,每一個介入程度都有 disclosure 的相關規範,只要有使用到 AI 就必須揭露在哪裡使用,又是怎麼用的,定義的非常清楚。

裡面有寫完整的 AI 導入過程,包含實際的案例以及老師、助教還有學生的心得感想,由於這個過程很詳細,碰到的挑戰、困難跟心路歷程也都在上面,所以真的非常值得一看。

第二篇是滕雅辛(幽素)的《置身钉内》

釘釘是中國阿里巴巴集團做的一個辦公軟體,類似於 Slack,但更像是 Teams,功能更多、速度更慢。他是一個叫做 ONE 的新專案的 PM,ONE 想利用 AI 來做一個嶄新的辦公軟體,用 AI 幫你整理工作然後重新排序,例如說自動幫你摘要你漏掉的消息啦,早上提醒你今天該做些什麼啦等等。

然後結論是這個產品失敗了,而這篇就是以他的視角重新講述一次整個故事,他們怎麼做這個產品,在他看來又為什麼失敗。

這篇之所以好看也是因為他很詳細,裡面很多細節(所以也很長,說是有 7 萬字),而且各個層面上都有探討,例如說產品面碰到了哪些問題,制度面又因為大公司碰到哪些問題,裡面一定有些情節是會讓大家感到似曾相識的,然後也能看到中國的這些公司到底有多卷。

無論是產品本身定位上的矛盾也好(到底要服務誰,付錢的人跟用的人不同),組織內的溝通協作也好,看了應該都會有點感觸。

這篇原本似乎是被貼在阿里的內網,後來才被轉到外面,然後釘釘的副總裁看到後寫了一篇《置身钉外》,是他離職後寫的,這篇短很多,看不了長文的朋友們不用擔心。

裡面我印象深刻的是:「有时候我会想,如果我要用失去所有生活的代价实现一家公司的理想,那我又有什么资格描绘 AI 改变世界的蓝图?」,讓人不禁思考工作到底是為了什麼。

推薦給大家。

GitHub RCE 與 AI 逆向

四月底的時候 GitHub 有爆出一個嚴重的 RCE 漏洞 CVE-2026-3854,只要有 push 權限就可以拿到 RCE,是由資安公司 Wiz 回報的。

總之就是 GitHub 裡面有一個 X-Stat 的 header 會在內部傳遞,是用分號 ; 來分割 key 跟 value,然後在 push 時帶上的 option 會被放在裡面,而這邊的編碼沒做好,導致你可以在 option 傳 abc; test=pwn; 去影響到 X-Stat 最後解析出來的值。

而這個 X-Stat 有幾個有趣的值如 rails_env、custom_hooks_dir、repo_pre_receive_hooks 這些看起來就可以利用的東西,最後只要把這些覆蓋掉,就可以用 GitHub 本來就有的 pre hook 機制去執行任意指令,串成 RCE。

那這 X-Stat 的 header 是怎麼被發現的呢,GitHub 本身可不是個開源軟體。

雖然沒開源,但是 GitHub 有提供你可以部署在自己主機上的企業版,給你一個 VM 跑起來,而這個 VM 裡自然也會有 GitHub server 的 binary,你把這個 binary 逆向就行了。

Wiz 的文章裡面有特別提到,AI 在這部分幫了很大的忙,他們以前就想做類似的研究但成本太高,現在靠 AI + IDA MCP 加速很多也降低成本,才發現這條路徑。

感覺這種事會越來越常發生,對那些編譯過的 binary,要做白箱的話需要先逆向解開才能挖洞,需要一定成本跟前置知識,像我這種幾乎不會逆向的就玩不了。

但現在有 AI 幫我逆向了,想研究的東西丟給 AI 幫我逆一逆,我也是可以看到 source code 了,就不會受到原本的限制。不過對我這種外行人來說,AI 解不開的 binary 照樣沒輒就是了。

之前解一個手機上 .so 檔,類似 VMProtect 那樣的東西 AI 就沒完全解開,還一直跟我說什麼「這個需要資深工程師花兩週,成本太高」,我只能一直安撫他:「你可以的,你很厲害,加油」,但解了兩三天燒了一堆 token 沒解開我就先放棄了。也不是完全沒有進度,有在推進了但沒完全還原。

AI 與工程師未來

前陣子又思考了一下自己對於 AI 還有軟體工程師這個職業的看法。

會再次思考的轉捩點有兩個,一是之前分享過的,用 AI 做逆向的時候發現 AI 的能力比我想像中的厲害許多,真的被驚艷到了。

二是在工作中見證了 AI 的強大,例如說設計在某些狀況下可能直接被跳過了,因為 AI 就能直接給出可接受的解答(至少對內部系統來說)。

那為什麼軟體工程師不行呢?如果越來越多工程師只是把 spec 或是需求丟給 AI 讓 AI 做,review 也給 AI,那需求方是不是也能跳過工程師,直接用 AI 把東西做出來?這點在一些小需求上面已經是這樣了,已經有很多不會寫 code 的人靠 AI 做出了滿足自己需求的產品。

有些人可能會反駁說:「可是 OOO AI 辦不到啊,做得很差」,這個 OOO 你可以帶入如資安、部署、合規或是性能調整等等,任何你覺得 AI 現在做不到的事情。

兩年前我也覺得 AI 做不到融合現有產品寫 code,只能拿來寫新的小玩具而已。一年前我也不覺得 AI 可以從頭寫出一個具有完整度的產品,而且自己測試。

在談 AI 能力的時候,我常常會想,這些做不到的事情,是現在做不到,還是以後也一定做不到?或是,腦海中能不能想像 AI 做到的樣子?

如資安,以前 vibe coding 常被詬病資安很差,但現在 AI 在資安上的能力越來越強,你寫完 code 只要讓他自己再 review 一遍資安,我是覺得基本常見的漏洞應該都找得出來。

最近碰到這種問題時,我的思考模式已經漸漸轉變為:「既然 AI 做不好,你該做的不是說 AI 不好用然後放棄,而是教 AI 做好」。

你覺得 AI code review 不好,就把你怎麼 code review 的經驗分享給他;你覺得 AI 找不出漏洞,就把你找漏洞的心得跟流程分享給他,要他學著點。

雖然說人腦中的知識跟經驗很難完全 dump 出來,但提供一些方向是做得到的,或也可以提供一個 checklist 讓 AI 慢慢勾,有足夠 token 的話每一項開一個 subagent 去跑也行。

總之呢,我從認知到 AI 的強大之後,開始重新思考軟體工程師會不會被「取代」(這個取代有很多不同層面上的意思),再思考軟體工程師的職責到底是什麼,被取代的前提又是什麼。

然後又想到了團隊分工的轉變,以前做 prototype 都是 PM 自己先弄個 wireframe,然後設計幫忙,現在一步到位 PM 直接寫 code 出 prototype 了,還可以沿用已經有的 design system。

簡短摘要就到這裡,其他細節都放在文章了,聊的東西比這邊多而且思考過程更完整,對這話題有興趣的話可以看看。

Google 索引被拔光

前兩天看了一下很久沒看的 search console,發現我的兩個部落格在 5 月初的時候, index 被 google 拔光光了,直接歸零,現在去搜什麼都搜不到 😅

既然 index 都被拔掉,那從 google 過來的流量自然而然也歸零了

還有另一個完全不同 domain 的網站(之前架的共筆部落格)也是差不多時間,在五月初 index 全部被拿掉然後歸零

由於我什麼都沒更新,應該不太像是網站的技術問題,網路上搜了一下好像也不少人也類似的狀況,給我的感覺是 google 演算法改壞了,或是我的網站被誤判為是 AI 電子垃圾吧

有在後台請求了一下重新建立索引但就是很慢,而且也不一定會有效果。只能說船到橋頭自然直吧,等他哪一天自己好起來。

npm 供應鏈防禦

最近每隔幾週甚至幾天就看到新的供應鏈攻擊的新聞,最多的是 npm,再來 PyPI 也不少,別的生態系平常用得少就沒在關注了。

趁著這主題正夯,把拖稿半年的文章寫完了,這邊先整理個精華版。

當你執行 npm install express 的時候,npm 會先去看 express 最新的版本是多少,接著下載。然後呢,express 本身也依賴很多其他套件嘛,就會根據 express 的 package.json 去找這些套件,然後再遞迴去找所有依賴,全部都下載下來。

而 express 的 package.json 可能是寫說「某個套件 2.x.x 版本我都接受」,因此若你安裝的時候剛好有個駭客幫某個套件發了新版,你就自動下載到最新版,然後就 gg 了。

之所以下載即 gg,是因為 npm 的套件可以寫一些 scripts,例如說 postinstall,安裝完就會自動執行這個 script,所以套件就寫個惡意腳本放到 postinstall,你下載完執行,就被駭了。

但這功能其實是可以關掉的,關掉就少了一個攻擊面,雖然還是有可能下載到惡意套件,但至少不會在下載後就直接執行惡意程式碼。

話雖如此,能不下載到惡意套件當然是最好的。

目前最好的防範方式是設置一個 min release age 的參數,可以加一個「延遲時間」,例如說 3 天好了,代表你只允許下載 3 天前發布的套件。由於現在也不少資安公司在做防護,所以惡意套件通常 1 天內就會被發現而且下架,3 天應該滿夠的。

再者,如果不是第一次安裝,也能透過 lockfile 去鎖定版本(這很重要),確保每次下載的版本是一樣的,不會不小心下載到最新版。

那把 scripts 關掉又把 min release age 設定成 3 天就安全了嗎?還沒,因為除了可以去 registry 下載套件之外,其實也能從第三方 URL 跟 git URL 去下載,這兩個又會有各自的其他問題。

昨天寫了一篇部落格文章,想仔細了解的可以看一下,不用留言任何關鍵字,我也不會私訊你什麼大禮包,你點一下就看得到了。

懶得看的話,最懶人的做法是改用最新版 v11 的 pnpm,它預設的設定就幫你擋了很多東西,怕的話再加裝個 sfw(socket firewall),至少能擋掉絕大部分的攻擊。

TanStack 供應鏈攻擊

上週知名的前端開源套件 TanStack 被供應鏈攻擊,連 OpenAI 的員工也慘遭毒手(?)

稍微看了一下 TanStack 發的 Postmortem,剛好這塊我小熟,可以稍微聊一下。

這次打進去的管道一樣是俗稱的 Pwn Request,只要發一個 Pull Request 就能打進去,偷到 npm token 或其他 credentials,就可以拿這個來發版,根本原因就是 CI workflow 有問題。

不過這次的 Pwn Request 算是一個變形版本,先來講最經典的版本,就是你拿來跑 PR 的 workflow 權限沒設好,讓人可以讀 secrets 等等,一跑就直接拿到。

這次攻擊是利用 cache poisoning,在跑這個 workflow 的時候,其實本身偷不到任何 secrets,這段的權限配置是沒問題的,所以我才說是變形版。

有問題的是,當 workflow 跑完之後,會把 pnpm store 存到 cache 中,而這個 cache 是「整個 repo 共用的」,而非 by branch 或是 PR 獨自用一個。

也就是說呢,攻擊者在 PR 裡面加了一段程式碼去污染這個 pnpm store,在 workflow 結束以後,這個被污染過的版本就被存到 cache 裡,而下次發版的 workflow 執行時,就讀到了這個被污染過的 cache,執行裡面的東西,此時發版用的 token 已經在 memory 裡了,就 dump memory 以後就能拿到 token。

算是一種橫向移動,你從低權限的地方寫 cache,而高權限的地方讀 cache 時就會被污染,你就移動到了高權限的環境。

為什麼會說我小熟,是因為之前打滲透測試的時候有打過一個 CI 類產品,那時就有稍微研究了一下 Pwn Request 有哪些方法可以打,就發現了 Adnan Khan 在 2024 年寫過的這個 cache 污染手法,那時打的案子也有類似問題,我是直接回報說平台本身應該把這個修掉。

而 GitHub 雖然也在 GitHub Actions 安全文章裡提過這類問題,不過看起來不把這個視為要修掉的漏洞,比較像是 by design,然後要使用者自己注意。我最喜歡這類的 bug 了,就是平台不覺得這需要修,責任拋回使用者,但使用者不知道就是不知道,會用錯的還是會用錯,但知道的一眼就能看出問題在哪。

Claude 訂閱制新限制

話說前幾天 Claude 發了個公告,從 6/15 開始 Claude Agent SDK 或是 claude -p 這些方案都要走另一個 pool,你每個月繳 100 美金就是 100 美金的 token 錢可以用,超過的額外算錢。

目前最多人用的兩套訂閱制,一套就是 Claude code,另一套是 OpenAI 的 codex,都有提供每個月 100 美金或是 200 美金的方案,使用額度給得滿高。

為什麼大家喜歡訂閱制?因為對於高用量的人來說,訂閱制超級省錢。你每個月繳 100 美金,但用到的 token 數量正常算錢可以到 1000 美金甚至更多,價差足足到了 10 倍以上,畢竟這些最前沿的模型真的不便宜。

而對提供模型的廠商來說,目前看起來這方案也不像是靠一堆買了沒在用的使用者來打平或賺錢,更像是一種補貼,為了吸引更多使用者來用,因此自行吸收部分成本。

這次調整過後,只有「一般個人使用 Claude Code」沒問題,依然照本來的訂閱制走。你只要想把 Claude Code 全自動跑、拿去其他軟體跑,都是走新制度,頂多就用到 100 美金,不能再多了。最常見的就是 claude -p,像我以前提過的 Paperclip 或是有些人會做個在 CI code review 的機器人,這個都一併被排除了。

所以要嘛就是跳槽到 codex,要嘛就是乖乖付 token 錢,再不然現在也開始有些人想把 claude -p 用正常交互式 Claude Code 重新實作來繞過 😆

不過既然是補貼方案,那這種訂閱式很有可能會有消失的一天,一律照 token 收費,到時候許多高用量的人開發成本大概會多 10 倍(除非你換模型)。有訂閱制堪用直須用,我 Claude Code 跟 codex 都用過,覺得各有各的好,我覺得 Claude Code 的解決問題能力更強,codex 則是 GUI 滿好用的,沒體驗過的人建議都可以體驗看看。

神奇的隱形水印

今天來聊聊隱形水印這個神奇的東西。

浮水印 watermark 大家應該都聽過,為了防盜圖什麼的很常看到這個,而隱形水印就是「看不見的浮水印」,invisible watermark,明明加了浮水印在圖片上但肉眼看不到。

大家要知道肉眼能辨識出來的東西是有限的,例如說許多圖片的壓縮可以從 2MB 壓到 200KB,大小變成 10% 但是肉眼看到的幾乎一樣。而隱形水印也是在肉眼看起來幾乎相同的前提下,把一些資訊塞到圖片中,你人看是絕對看不出來有這東西的。

隱形水印的應用最常見的有幾個,第一個是追蹤外洩資料的來源,例如說漫畫 APP 想知道盜版網站的圖片是從誰流出去的,就能根據隱形水印找到 user id,第二個是 AI 標記,例如說從 Google 那邊產生的 AI 圖片都會用一個叫做 SynthID 的技術加上隱形水印,你把圖片丟給 Gemini 問他是不是 AI 產生的,他就會檢查。

厲害的隱形水印必須要對抗許多東西,例如說防壓縮,你壓縮完之後隱形水印還在。也要防 resize,你圖片換了個尺寸或是裁切過後也還在。當然,並不是說水印永遠不會消失,還是有可能不見的,但至少保證正常使用下,水印都會在。

除了圖片,影片也可以加隱形水印。

Meta 去年就發了一篇文《Video Invisible Watermarking at Scale》,講他們是怎麼做的,而主要的應用情境是在「誰第一個發這個影片」,這個應用滿不錯的,可以防止那種二次轉發想賺流量的,你把別人影片偷過來重發,就算剪輯了,還是能辨識出原始的上傳者是誰。

雖然圖片跟影片都行,但文字呢?文字要怎麼藏東西在裡面?

有種做法是用零寬字元,藏幾個看不見的字元在裡面,但問題是如果文字流出的方式是截圖就看不出來。也可以些微更改標點、排版或是同義字等等,來對抗這種截圖流出的方式,但這個就是肉眼可見了,你拿發給不同人的內容來看就會看到差異,不過這也沒辦法。

而針對 LLM 所產生的文字,Google 的 SynthID 技術也有 cover 到(真的好強,趕快多買一點 GGLL,我都直接兩倍槓桿),LLM 的原理就是不斷去預測下一個 token 是什麼嘛,然後每一次都會有多個候選,例如說「我喜歡吃」後面可能接「鳳梨」、「牛肉麵」、「章魚燒」等等,而 SynthID 就是在這個階段介入,用你想藏的文字算出一個 random seed,再搭配這個隨機亂數,讓每次的選擇都偏移一點,在文字越長的狀況下,統計來看就會越明顯。

簡單來講,就是讓 LLM 在選擇文字時會有特定偏好,但這個偏好小到你人類幾乎看不出來。跟「不是…而是…」這種被講到爛的 pattern 不一樣。

這個做法真的滿有趣的,可以做到人看不出來但是又根據 LLM 的特性塞了額外資訊在裡面。

Linux 提權漏洞解析

今天剛看到 Linux 最新被爆出來的提權漏洞 CVE-2026-31431,又稱作 Copy Fail,利用方式簡單容易。

用白話文講的話,你原本把重要文件放左邊,白紙放右邊,讀完左邊文件之後,在右邊白紙寫下筆記。

但你有天突然覺得這樣很不方便,比起左右放,還是上下放更好,於是上面放白紙,下面放文件,結果白紙寫著寫著寫滿了,不小心多寫了一些字在重要文件上面,文件的內容就被修改了。就因為這個不小心,重要文件的內容被改動,就成了一個漏洞。

修法很簡單,不要把兩張紙上下放在一起就好,讀就是讀,寫就是寫,要寫就寫白紙上,不讓你寫到重要文件去。

技術細節的話,這個 bug 出在 Linux kernel 的 authencesn 功能,是拿來做加解密的。正常狀況下,你丟給他一段密文跟 key,他就會把解密的結果寫到 buffer 後還給你。

正常來講讀寫是分開的兩塊 buffer,但由於 2017 年的一個改動,讀跟寫的 buffer 指到了同一塊記憶體,然後 authencesn 的實作又被發現了一個 4 bytes 的 overwrite。

所以你先用 splice 拿到 /usr/bin/su 的 page cache reference,當成 input 丟給 authencesn,接著再利用那個 overwrite,就可以蓋掉 su 在 page cache 中的內容,等於是修改 su 的程式碼。

蓋完之後再執行 /usr/bin/su,就順利 root 了。

整個 exploit 的重點在於可以寫到任意的 page cache,所以把你想改的 program 用 splice 拿到 page cache reference 後,就可以丟給 authencesn 用 bug 去覆蓋 page cache。

最後修法是把那個 in-place 的改動拿掉,不讓你寫 page cache。

(我完全不懂 Linux kernel,技術細節是反覆看 writeup 以及與 AI 討論得出來的,細節必有不精確之處,有錯的地方歡迎留言指正,讓我多學習一些 Linux 知識)

身分證字號不是鍵

這兩天看到一個在講身分證字號的新聞,三年前台灣個資外洩的新聞爆發之後,有人因為這個去申請改身分證字號,被行政機關駁回後提起訴願,然後打行政訴訟,最後打贏了,可以更換身分證字號。

讓我想起以前看過的法律白話文運動的貼文,尾數是 4 或是含有三個以上的 4,也能修改身分證字號。

由此可見,身分證字號是會變的,所以存在系統的時候不要用這個當 key,否則會出問題。

還有另外一個理由是,身分證字號是有可能會重複的。

以前人工作業時抄寫錯誤等問題,導致同一個身分證字號可能出現在兩個人身上(隨手搜一下就很多資料了),就需要有一個人去改。

總之呢,身分證字號既不 primary 也不 unique。

參考資料:https://www.cw.com.tw/article/5140846

用 Agent 清理硬碟

話說 agent 是真的很方便
以前我電腦容量快滿的時候,不想去下載一堆感覺就不太安全的 cleaner,也懶得裝一些開源的軟體去掃

但有了 agent 之後,我現在都直接讓 agent 做了
就打開 cursor CLI 跟他說我空間快滿了,幫我找找哪些地方佔空間
他就會開始跑跑跑透過各種指令去看空間分佈

掃了大概 10 分鐘就給了份報告,跟我說 npm 的快取就 10GB 了,pnpm 5GB,Go 的也有個 2GB,Playwright 也有 10GB,超多版本的 Chromium 都在裡面,大概裝了二十個。

總之就是各種應用程式的快取佔了一堆空間,最後幫我分析哪些可以清掉,但最後清掉的指令跟刪除還是我自己來執行,他只幫我分析而已。

刪完再跑一次就跟我說少了多少空間,哪裡還可以在刪等等,真滴方便。

Claude 訂閱與工具限制

4/6 07:00 更新:

一早起來看到 Peter Steinberger 的推文,就算用 claude -p 只要你帶上 OpenClaw 的 system prompt 還是會被 ban,所以之前我的理解可能有些偏差,就算你自己 claude -p 給龍蝦用也還是不行(Peter Steinberger 原本也以為可以 😂)

雖然說只要把那段字串稍微改一下就會過,但官方的態度就擺在那裡。之後等等看有沒有個官方聲明好了,再繼續更新這篇貼文。

===

小聊一下 Claude 訂閱制把第三方工具 ban 掉這件事

如果我的理解沒錯,無論是 Claude 的訂閱方案也好,還是 Google Antigravity 的訂閱方案,使用規則都是一樣的,那就是禁止你把訂閱方案的 token 拿去其他非官方工具用。

其實最大的那幾間,所謂固定費用的「訂閱制」,本來就不是針對模型本身,而是針對產品,是讓你使用他們產品的時候可以用得更多,卻只需要付出固定費用。若是你有其他客製化需求,就是去接 API,一律使用 API key 的方案按量收費,否則就是違反使用條款。

Claude 的立場從以前就這樣了,上次對 OpenCode 也是一樣,不是不能用 Claude 模型,而是你不能用訂閱制拿到的 token 去使用,要用的話就要用 API key。

有用過的都知道,認真在用的話訂閱制一定是比 API key 便宜的,一些 AI 中轉站的原理就是這樣,背後有一堆訂閱制的帳號,然後把 auth token 拿出來轉成呼叫 API 的形式,用這些固定費用的帳號創造出更大的利益來賺價差(顯然不符合官方使用條款)。

雖然可以理解訂閱制與 API 的差異以及官方的考量,但身為使用者的我們當然還是想省錢,除了換個模型以外還有其他做法嗎?

有的,第一個是用 OpenAI 的 codex 訂閱方案,OpenAI 目前並沒有禁止把訂閱方案用在 OpenClaw 上面,所以我之前架小龍蝦來玩,第一件事情就是訂閱 codex 方案。

如果你是開發者想要寫一點自己的服務,那正解就是參考 Paperclip 的做法,與其接入 AI 模型,不如接入 AI agent。在 Paperclip 的模式中,他直接接入 codex 或是 Claude Code 等工具,幫每一種工具做一個 adapter,然後用 headless mode 跑起來。

換句話說,當你建立一個任務時,背後是直接去跑 claude -p “analyze this repo for security issues” 並把結果回傳。因此最後跟 Claude 模型的互動還是透過 Claude Code,這是完全符合規則的。

面一些論述的出處做為佐證。

參考資料:https://x.com/steipete/status/2024182608746217953

Blockly 翻譯鬧笑話

今天突然想查 Scratch 用的那套可以用類似拼圖的方式寫程式的東西叫什麼,我記得有人有開源出來,查一查發現 Google 開源了一個叫做 Blockly。

於是我就去官網看了看介紹,看到底下這段超級突兀:

「禁止使用網頁版」

我就想了想為什麼要禁止使用,還要當成一個功能來宣傳,把語言切成英文後恍然大悟:「Blockly for web」…

底下那個「為什麼要封鎖」,也理所當然的是「Why Blockly」。

真有你的,Google。

Claude Code 原始碼外洩

今天早上看到 Claude Code 原始碼因為 source maps 外洩的消息,我第一個反應是:「咦?難道以前沒有人試著還原過?」

Claude Code 的程式碼雖然沒有開源,但其實就是個 13MB 的 cli.js 檔案,俗話說的好,client 端的東西沒有秘密,而且還是最容易還原的 JavaScript,那以 Claude Code 這麼有名的東西來說,不可能沒人研究過吧,怎麼就變驚天的重磅消息了,好像知道了許多以前不可能看見的東西。

經過了一整天的思考,這想法其實半對半錯,聽我娓娓道來。

先來講講 source maps 是什麼,前端的程式碼需要用 bundler 打包在一起,打包完之後會做 minify 跟 uglify 等操作,去掉所有多的空白、換行,然後把變數名稱都變成 a,b,c 那種可讀性低的格式,最後的產物才會傳上去。

但既然程式碼可讀性都變這麼差了,要 debug 的時候怎麼辦呢?這時候就需要把這些 minify 過的程式碼還原成原本的樣子,靠的就是這個 source maps 的檔案,裡面記錄著原始的程式碼以及對應關係,靠這個檔案就能對應出原本的 a2 其實是 API_URL 這個變數。

所以若是 source maps 裡面記錄著檔案路徑以及內容,這個檔案洩漏就等於是原始碼洩漏了,這就是此次 Claude Code 發生的事故。一般常見的做法是 build 完一樣產生 source maps,但是不上傳到外面,只上傳到 Sentry, Datadog 等專門做錯誤處理的地方,在那邊還原,就能確保原始碼不外洩,又能方便 debug。

這邊再提一個概念,有些人會把 minify 跟「混淆(Obfuscate)」混在一起,這兩個概念不一樣。混淆指的是特地把程式碼再轉換一層,你光看是絕對看不懂的,惡意軟體就常幹這種事。而 minify 更像是把程式碼的體積縮小,你認真看還是能大概看出它在幹嘛,我看過很多遍了。

所以,Claude Code 大部分的功能,你根本不需要 source maps,你直接拿 AI 丟給他 cli.js(或先稍微處理過),他就可以回答你了,該有的邏輯都在那邊。

那到底有哪些東西會在打包的時候被去掉,讓這些資訊徹底消失呢?最顯而易見的就是變數名稱、函式名稱、檔案路徑等等,以及最重要的:註解。

程式碼裡面的註解在打包後會完全被去掉,而 source maps 裡面則被保留。以及另一個我朋友提醒我才想到的:dead code。

Dead code 指的是永遠不會被執行的程式碼,例如說 if(false) { … },這段永遠不成立。那為什麼有人會寫出這種程式碼呢?通常原始形式其實是這樣:if (Flag.Internal) { … },然後在 build 的時候把 Flag.Internal 換成 true 或 false,藉由 feature flags 的方式在 build time 開關,藉此 build 出不同的版本。

如果 Flag.Internal 是 false,那最後的產物就會直接把程式碼去掉。但是呢,由於 source maps 保存的是原始檔案的整個內容,因此這些 dead code 還會在。

總而言之,這次外洩的 source maps 跟原先打包後的版本比起來,多了以前絕不可能看到的註解與打包時被移除的 dead code,也還原了變數名稱與檔案路徑。

換句話說,很多人寫的什麼「Claude Code 的隱藏功能」也不是真的隱藏,只是大家懶得去看打包後的版本而已。

之所以我敢寫得這麼肯定,是因為我去試過了。外洩的版本是 2.1.88,我抓的是 2.1.87,我先讓 AI 幫我研究 Bun 的 bundler 邏輯,然後寫一個 reverse 版本,先把 cli.js 還原成 50 個小檔案,然後讓 AI 再根據這些檔案幫我還原成合理的形式。

接著我讓 AI 整理幾篇網路文章提到的隱藏功能,讓他去找找在不在程式碼裡面。

關於那些註解、內部代號或是特殊 flag 才能開啟的功能,確實不存在。例如說什麼內部代號 Capybara、Fennec、Numbat 等等,還有 Undercover Mode 跟反蒸餾防禦,這些都找不到。

但是今天上線的 BUDDY 電子寵物系統、KAIROS、ULTRAPLAN 或是記憶管理、壓縮邏輯等等,這些都是有的,本來就存在了。

所以呢,如果有人有心想研究的話,Claude Code 的這些運作邏輯一直在那,事實上也有人逆向過了,這些都不是新鮮事,只是大家懶得去做而已。那些 prompt 啦,記憶系統啦,agent 協作啦,bash 的檢查啦,憤怒語言偵測器啦,不需要 source maps 外流你就看得到。

真正全新的東西是那些註解裡面寫的經驗、內部代號以及 build time 被砍掉的隱藏功能,這些確實是只有透過 source maps 能看到的。

寫了這麼多,我只是好奇心使然,想去探索到底有哪些東西是新的、真的外洩的,哪些東西又只是「你想研究一直都在,只是現在不用自己還原」,也順便測一下 AI 的能力(還原 bundle 過的程式碼)。無論如何,原始碼外洩對於想研究的人絕對是利多,不用自己去試著還原或是猜測,有原始碼什麼都好辦。

或許在某個平行時空,有個好奇的人辛辛苦苦逆向了 Claude Code 把架構還原,準備跟大家分享成果,結果一覺醒來發現原始碼外流了,每個人用 AI 產的文都跟自己苦心研究的成果類似,只能躲回被子裡哭。

Trivy 供應鏈攻擊

剛好整起事件都有跟到,來聊一下 Trivy 跟最近的大規模供應鏈攻擊事件。

Trivy 是個資安公司 Aqua Security 出的開源掃描工具,最常用的是拿來掃 IaC 的程式碼或是 image 之類的,我自己就用過不少次。

在 2 月底的時候 Trivy 的 GitHub 被攻擊,因為 CI 流程有漏洞,所以發個 PR 就可以偷到 token,這類攻擊通常被叫做 Pwn Request,以前也出現過不少次,而這次的攻擊其實不只有 Trivy 受害,一堆 repo 也被攻擊了。

攻擊的帳號叫做 hackerbot-claw,跟上了前陣子正熱的小龍蝦熱潮,我那時看到消息還想說是不是哪個資安研究員在做研究 😆

過了幾週,到了 3/19 左右,駭客正式發起攻擊,透過 2 月底偷到的 token 直接幫 Trivy 發個含有惡意程式碼的新版本,甚至更狠地還把舊的 tag 全部都 push 一遍。

有些人已經有意識到這類型的供應鏈攻擊風險,在使用一些套件時會寫死版本號如 trivy@1.2.3,這個通常是沒問題的,因為許多 package manager 會保證版本不可篡改,例如說 NPM。

但是 GitHub Actions 沒這功能,他的版本只是一個 tag,背後東西是可以換的。所以你在使用 action 時寫死 tag 也沒用,要寫死 commit hash,這我也是今天才知道的,之前沒注意到這個差異。

看到這邊我相信大家都有個疑惑的點,那就是為什麼二月底被駭,理論上已經清理過一輪了,怎麼 3 月底又來一次,而且還是用二月就被偷的 token。

官方聲明是這樣寫的:We rotated secrets and tokens, but the process wasn’t atomic and attackers may have been privy to refreshed tokens

具體是什麼狀況沒講,但總之應該就是換的時候沒換好,導致攻擊者也能拿到新的 token。雖然說大家都會犯錯,但是一個資安公司連錯兩次,客戶對他們的信任度可能掉了不少…

總之呢,開頭提過 Trivy 是掃描工具,所以一堆專案都有裝這個,那自然也一堆專案直接被入侵。為了安全裝了資安掃描工具,卻因為裝了這個被入侵,有點諷刺。

而目前最新的受害者是今早才爆出來的 Python 套件 LiteLLM,被入侵的管道就是之前 Trivy 被駭的時候偷到了maintainer 的 token,就利用了這個 token 發布惡意版本。

就是巢狀供應鏈攻擊啦,先打下一個套件,再打下用這個套件的套件,以此類推,越打越多,影響也越來越大。雖然說 LiteLLM 有問題的版本已經被快速下架,但是大多數人(包含我)都猜測攻擊還沒停止,一定會有下一波的到來,請大家多多注意。

防範的方式還是老樣子:

  1. 安裝套件的時候永遠固定版本
  2. 承上,在某些版本不是 immutable 的情境下要固定 hash(如 GitHub Actions)

如果要安裝的專案是別人的,別人沒有寫死的話,也建議加減裝個 socket 之類的,在下載後似乎會先做一些基本掃描,也算是多少有防到。想更安全的話就是在 VM 或是 docker container 裡面裝,至少能保證影響範圍有限。

話說單個套件被打就已經這麼恐怖了,何況是整個 package manager 都被打下來。之前在 DEVCORE CONFERENCE 2026 聽到 splitline 的議程,就是在講直接去把整個 package manager 打下來,而且成功了不少,涵蓋一堆程式語言。簡報要四月底左右才會公開,到時公開了再來分享一波。

參考資料:https://snyk.io/articles/poisoned-security-scanner-backdooring-litellm/

把 DOOM 藏進 DNS

剛看到一個國外的資安工程師 Adam Rice 因為太喜歡 DNS 了,所以乾脆把 DOOM 毀滅戰士放在上面,只要依序解析 DNS TXT 紀錄就可以抓下來跑 😆

先來講講 DOOM 毀滅戰士這個遊戲,如同原文所提到的,一堆神人會在各種地方試著把 DOOM 跑起來,例如說有數位螢幕的驗孕棒或者是電動飛機杯之類的。

而 DNS TXT 紀錄本質上就是個字串,每條紀錄可以放 2000 個字元左右,所以把 DOOM 的主程式壓縮一下再轉成 base64 約 3MB ,作者用了將近 2000 條 DNS 紀錄把它給放進去。

最後,只要寫個 PowerShell script 去解析 DNS 拼接成一個大字串,在記憶體裡面解碼然後解壓縮,就能直接把 DOOM 跑起來,做到檔案不落地,直接在記憶體裡面跑。

更多技術細節在原文,然後原始碼也有開源到 GitHub 上。

Coupang 外洩與金鑰

今天從技術的觀點來聊前陣子沸沸揚揚的 Coupang 個資外洩事件。

其實已經寫一篇完整的部落格文章了,懶得看全文的話,就看我這篇精簡版吧。

Coupang 是個韓國電商,在台灣也有設點,去年發生個資外洩事件,韓國那邊的調查已經告一個段落,而近期因為台灣也有受影響,所以數發部介入,目前劇情大概到這裡。

相關的技術細節韓國的報告寫得很清楚,這整起事件的攻擊者並非外部駭客,而是一個離職的前員工,而且還是開發備援 auth 系統的 Staff Back-end Engineer(但他做這件事的動機新聞跟調查都沒寫)。

Coupang 的驗證系統在登入過後會發一個類似 JWT token 的東西,直接在裡面帶上會員 id 之類的,下次就只驗這個 token 是否合法。因此,只要能拿到簽這個 token 的 key,就能偽造任何人的身份,不用登入就獲得相關權限。

而這個離職員工就是利用這種方式,還在職時拿到了這把 key,偷偷帶走,離職後拿來偽造出 token,就能進入 my information 之類的頁面看到個資。

所以呢,這整起事件就是負責開發 auth 系統的主任後端工程師,在離職後用在職時取得的 auth 系統 signing key 搞出來的。

接著可以從兩個角度聊,一是 key 該怎麼管才安全,二是這種驗證方式本身是不是有點問題。

管 key 的話,有很多公司都會用 vault 或 secret manager 之類的東西管,然後讓 SRE 或開發者自己產一把 key 放進去。雖然說放到 vault 後取用是安全的,但產 key 的時候已經有幾個人知道了。雖然說 insider 的風險跟其他比沒這麼高,比較容易被查出來,但若是發生了,外部也不會管你到底為什麼出事。

所以不只是儲存跟使用,在產生 key 的時候也要注意,最安全的是用 HSM 儲存 key 外加 KMS 管理,key 本身從不離開這個系統,但相對的成本也會高一點。

也可以先從 key rotation 做起,當這些能碰到的人離職時,把能碰到的 key 都先換過一輪,雖然在職時還是能碰到 key,但至少讓他們離職後自動喪失所有權限。

再來,key 被偷就整個 auth 系統 gg,聽起來似乎不太合理。

以傳統 session 做法來說,你保存一個 session id,每次後端查表,session id 若是不可預測,你拿到 signed cookie 的 key 也沒用。JWT 其實也是,你如果在 token 裡存的是 session id 也一樣。

但現在許多系統 JWT 是存 session data 的,裡面直接放 email 或 user id 這些可預測的東西。在這個前提下,保護 key 就變成非常重要的一件事情,而且 private key 跟 public key 都要保護。前者保證不被洩漏,後者保證不被置換。

我相信有許多公司在產 key 這段多少都有點問題,許多都是我前面說的,由人產完再放進去 secret manager。況且也沒這麼多公司有資源專門去弄個 KMS(或甚至沒想到可以這樣或需要這樣做)。

這些都是風險,都會回到風險管理的框架去討論,不少公司目前選擇的是接受風險,亦即承認風險的存在,但因發生機率小所以先不處理。若是真的有哪個能碰到這些的離職員工偷偷帶了一份資料走,那類似的事情很可能又會重演。

總結就是:

  1. key 的完整生命流程要注意,尤其是產生的時候
  2. 使用 stateless JWT 有個風險是 key 被偷走就 gg,要記得
  3. 考慮風險時,除了外部攻擊者,也要考慮 insider threat

看完想知道更多細節的話,可以再回去快速看過部落格完整版

補充文章:https://www.msit.go.kr/eng/bbs/view.do;jsessionid=iMyzX8C42zedbf27PtWxq844qjcyYy0VOCt74FEO.AP_msit_2?sCode=eng&mPid=2&mId=4&bbsSeqNo=42&nttSeqNo=1221&utm_source=perplexity

這裡不是 AI 洗稿場

不好意思,你找錯地方了

這裡不是接入 AI,自動搜集新聞,自動改寫文章洗稿抄襲的地方

你找錯地方了

這裡不是視著作權於無物,直接翻譯國外文章或影片然後全文轉貼,又不附出處的地方

你還是找錯地方了

這裡不是用 AI 寫一堆故事,下聳動標題,不查證真實性,只管故事本身能否吸引流量的地方

你真的找錯地方了

這裡不是一直說自己 AI 用得有多厲害多跟別人不一樣,然後賣你課程的地方

就跟你說你找錯地方了

這裡不是每天發一堆 AI 新聞,每天都分享人類文明的重大突破,販賣焦慮的地方

喔喔喔,這次你總算找對了

這裡是想不出聳動的吸引人的標題、跟不上時代,就算寫得比 AI 差還是遵循古法手工製造的,我一個人發廢文的地方

GlassWorm 木馬攻擊

最近有認識的朋友中了木馬,本機 token 被偷光以後,直接往 GitHub 上的 repo 推了惡意程式碼,因為好奇就跑去稍微看了一下。

推的 code 是一段 JavaScript,會在 postinstall 的時候執行,惡意程式碼本身是用 unicode 的不可見字元,再寫一段 JS 還原然後丟給 eval,所以把 eval 改成 console.log 就能看到跑了什麼。

而這段程式碼解出來之後,是一段用 AES fixed key 解密另一個 payload 再丟一次 eval 的程式碼,所以要再改成 console.log 跑一次。

跑完之後還沒結束,會看到一段去呼叫 blockchain 的 API,從 Solana 的某個固定地址拿 memo,拿到的內容是一個 IP,接著連線到 IP 之後又拿一段 payload 回來,再丟到 eval。我連過去的時候被擋掉了,所以也沒看到具體 payload。

上網查了一下發現這是個叫 GlassWorm 的已知木馬,專門打開發者的,透過 VSCode 的擴充套件打進來。而我朋友中的這波是上週才發生的最新一波攻擊。

這次的攻擊是先發佈一些看似無害的套件,接著在升級時偷偷在 manifest 裡面加上惡意的 dependency,升級後 VSCode 就會自動下載,然後就中招了。

中了之後就會把你電腦裡的東西都偷過一輪,然後再去感染其他人。就像我開頭講的那樣,直接把你有權限的 GitHub repo 都 push 一遍,若是有哪個觸發 CI 甚至自動發版了,那就又擴散出去了,因此才會稱為是 worm。

這類攻擊感覺一直不斷發生,無論是 NPM 的 supply chain attack,或是針對 VSCode 套件本身的攻擊,都是專門打開發者,一不小心的話很容易中招。

也因為如此,我自己的 VSCode 幾乎都不安裝套件了,只裝官方而且夠大的,其他就算了。也把自動更新都關掉,避免新版帶奇怪的東西進來。

話說,現在好像越來越多人直接 CLI 寫 code,甚至連 editor 都不用了,因為寫完不用看直接上,其實也算是某種程度防範了這個風險 😆

不過取而代之的就會是一些惡意的 MCP 或 skill 等等,不小心跑了也一樣會有事。相關報導跟這次中招的套件,大家可以自己檢查一波。