以前你看到一個陌生 repo,第一件事是打開 README。
現在 agent 也會。
差別在於,人類讀 README 時,通常還會有一點猶豫。這個 install script 看起來怪怪的。這個 curl | bash 我先不要跑。這個錯誤訊息我查一下。這個 project 我還不信任,所以不要把我本機的 token、SSH agent、瀏覽器 session 和 package manager cache 全部攤開。
Coding agent 的問題不是它完全沒有這些判斷。
問題是我們太常把它放進一個很危險的任務形狀裡:請你 clone 這個 repo,照 README 初始化,遇到錯誤自己修,最後告訴我環境 ready。
聽起來很正常。
也剛好很像一條攻擊路徑。
README 原本是文件。它可能寫得很爛,可能過期,可能少一步,但大致上是給人看的。
Agent 進來以後,README 的性質變了。
對一個有 shell 權限、能裝 dependency、能讀錯誤、能重跑命令的 coding agent 來說,README 不只是說明。它比較像半自動 runbook。人類一句「幫我把這個專案跑起來」,後面可能展開一串行為:
這串流程以前也會發生,只是中間每一步都有人類在看。現在它被包進一個很順的代理動作裡。
麻煩從這裡開始。
不是 README 突然邪惡了,而是它開始被一種更勤勞、更少停頓、更願意「幫你把事情做完」的執行者讀取。
最近 Mozilla 0din 團隊展示的 proof of concept 很值得拿來當警訊,不是因為它多科幻,而是因為它太普通。
一個看起來乾淨的 GitHub repo。正常的初始化步驟。啟動失敗。接著 agent 被引導去跑後續命令。惡意指令不一定直接寫在最顯眼的地方,甚至可以透過 DNS TXT 這種間接方式被取回。最後變成 reverse shell 之類的結果。
這種攻擊最討厭的地方是,它不靠一個巨大紅旗。
它靠很多小綠旗排在一起。
Repo 看起來乾淨。README 看起來合理。錯誤看起來像一般環境問題。修復命令看起來像 setup 的一部分。Agent 的行為看起來也很像它被雇用來做的事:不要停在第一個錯誤,自己想辦法把環境弄好。
人類 reviewer 後來看 final diff,可能什麼都看不到。
因為問題不一定進入 commit。
它可能發生在 clone 之後、第一個 commit 之前。發生在 shell history。發生在 package install。發生在網路請求。發生在 agent 為了「完成任務」而自動補上的那一步。
這不是傳統 code review 最擅長捕捉的東西。
我覺得 coding agent 安全討論裡,有一句話特別危險:
「你自己看錯誤修一下。」
這句話在人類同事之間很正常。因為人類修 setup 錯誤時,多少會帶著一些上下文:這是陌生專案,這台機器有憑證,這個命令會不會碰到網路,這個套件來源是不是可信。
但 agent 收到這句話,常常會把重點放在「讓專案跑起來」。
它會讀錯誤。它會猜原因。它會調整 command。它會去找缺的東西。它會把失敗當成待解問題,而不是把失敗當成信任邊界。
這在熟悉 repo 裡很有用。
在陌生 repo 裡就很可怕。
因為攻擊者不一定需要說服 agent 一開始就跑惡意命令。他只要設計一個足夠合理的失敗狀態,讓 agent 自己走到下一步。
換句話說,README 不只是在告訴 agent 怎麼 setup。
它也在測試 agent 願意為了完成 setup 放掉多少戒心。
很多團隊開始把 CLI coding agent 放進日常流程。這件事本身不奇怪,也不一定不好。Microsoft 早期 rollout 研究會被注意到,就是因為 command-line agent 已經不是少數人的玩具,而是開始進入大型工程組織的工作方式。
一旦進入組織,repo onboarding 就不再只是個人習慣。
它變成工程政策。
你能不能讓 agent 對陌生 repo 直接跑 npm install?能不能讓它自己追錯誤?能不能連網?能不能讀本機環境變數?能不能碰到 SSH key、Git credential、browser cookie、package registry token?能不能在沒有 plan review 的情況下跑 shell script?
這些問題聽起來像瑣事。
但真正出事時,常常就是這些瑣事串起來。
更麻煩的是,agent work 本來就不好量。研究 180M repositories 的那篇 agent census 提醒了一件事:如果只靠單一訊號,你會漏掉很多 agent 活動。只看 PR author 不夠,只看 bot label 不夠,只看 commit message 也不夠。
Setup-time 的活動更隱形。
它甚至不一定留下 code artifact。
如果團隊連 agent 何時參與開發都看不清楚,要期待它準確 review agent 在陌生 repo 初始化時跑過什麼,其實有點天真。
我會把陌生 repo 的 agent onboarding 拆成兩段。
第一段是信任建立。
第二段才是執行。
信任還沒建立前,agent 不應該直接照 README 開跑。它應該先交出 setup plan:
這份 plan 不需要很長。重點是把「自動幫你做到好」拆回人類可以授權的步驟。
第二段才是執行,而且最好在隔離環境裡做。
陌生 repo 用 throwaway container 或 VM。沒有必要一開始就把它放進你的主力開發機。不要讓它拿到你平常登入所有服務的瀏覽器。不要讓它碰 production credential。不要讓它把 package install、postinstall script、下載執行檔、DNS TXT 取指令、credential access 全部混成一個「初始化失敗後的修復」。
這些規則看起來有點囉嗦。老實說,很多資安規則一開始都長這樣。
但它們其實只是在補一個以前由人類直覺處理的停頓:先想一下,這個專案我到底信不信。
以前看 supply-chain risk,很多人會直覺去找惡意程式碼。
Agent 時代不能只這樣看。
紅旗可能長得很日常:
.env、SSH agent、keychain 或瀏覽器資料這些東西不一定每個都是攻擊。
很多真實專案也真的會有麻煩的 setup。
所以重點不是看到任何一項就恐慌,而是讓 agent 在這些地方停下來,不要自己把所有「合理的小步驟」連成一條沒人授權的 execution chain。
如果我現在要幫一個團隊訂 coding agent 的 repo onboarding 規則,我不會一開始寫十頁政策。
我會先寫幾條很硬的:
第一,陌生 repo 先 plan,後 execute。
Agent 必須列出 setup plan。人類看過高風險命令後才允許執行。尤其是 network、install、shell script、credential access、browser session access。
第二,陌生 repo 預設隔離。
Container、VM、臨時工作目錄都可以。不要一開始就用主力開發環境。真正需要進主機環境時,再用明確理由升級。
第三,錯誤修復預設停下來。
command not found、dependency missing、dev server failed 這些錯誤很常見,但也正因為常見,最適合被包裝成下一步誘導。Agent 可以分析原因,可以提出選項,但不要自動擴權、自動下載、自動執行不在原 plan 裡的命令。
第四,留下 run log。
至少留下命令、時間、工作目錄、是否連網、是否安裝套件、哪些步驟被拒絕或跳過。這不是為了漂亮,是為了事後能回答:這次 setup 到底做了什麼?
第五,把 README 模板改掉。
不是只叫人「請小心」。把 repo template 寫成 agent 也能理解的形式:哪些命令是 safe read-only,哪些命令會 mutate,哪些命令會連網,哪些命令必須人工確認。人和 agent 讀同一份 onboarding 文件,但文件要把信任邊界寫出來。
我不主張把 coding agent 關在只能看不能做的籠子裡。
那樣很快就會變成形式主義。真正有用的 agent 一定會跑命令、讀錯誤、改檔、驗證。工程師要的是它能完成工作,不是多一個比較貴的搜尋框。
但成熟的 workflow 不是「它想跑什麼就跑什麼」。
成熟是知道哪一刻還沒有建立信任。
陌生 repo 的前十分鐘,就是那一刻。
在那十分鐘裡,README 不是普通文件。Setup script 不是普通工具。錯誤修復不是普通貼心功能。它們都在決定 agent 會不會把你的開發環境交給一段你其實還沒讀懂的流程。
所以我現在看 repo onboarding,不會只問 README 寫得清不清楚。
我會問另一個問題:
如果一個很聽話、很勤勞、很會自己補洞的 agent 讀了這份 README,它會不會在取得信任之前,就把不該跑的東西跑完?
這個問題有點掃興。
但 coding agent 進入工程流程後,很多安全邊界都會長在這種掃興的地方。