AI 程式碼安全審查
AI 寫得出程式,不等於它交付的是安全程式
AI 寫得出程式,不等於它交付的是安全程式
你將學到什麼
漏洞長什麼樣
heredoc 沒加單引號會先做變數展開,檔案內容直接變成可執行程式。
正確的寫法
heredoc 加單引號、變數改走環境變數傳遞,資料與程式碼絕不混在一起。
AI 審 AI
寫 code 與挑毛病要用不同 context,同一個 session 自我審查會有偏誤。
最後防線
commit 是本地可 reset,push 是公開爬不回來,push 只留給人類。
事情是這樣的,昨天晚上用 Claude Code 開了一個新專案的骨架 20 幾個檔案、7 個架構決策、5 個 hook、2 個 subagent、5 個 skill。全部都是 AI 寫的。然後我差點把一個 Remote Code Execution(RCE)漏洞給 commit 上去。
但!抓到這個漏洞的不是我,是另一個 AI。幸好我有「用 AI 審 AI」的習慣,不然真的會 G 掉!
所以這篇文章不是要跟你說「AI 寫 code 多厲害」,而是要很誠實的告訴你:就算是很強的 AI 所寫的 code 也會有漏洞,而且會是你一時之間看不出來的漏洞。
事情是這樣發生的
我請 Claude Code 幫我寫 5 個 hook(.claude/hooks/ 裡面那種),其中一個叫 block-secrets.sh,職責很單純:在 Claude 要寫入任何檔案之前,檢查檔案內容裡有沒有 API key、密碼、.env 這種敏感資訊。有的話就擋掉。
看起來很安全對吧?畢竟 Hook 本身就是拿來做 security 的。
Claude 很快寫完了,我瞄了一眼,覺得邏輯很合理,用 bash 收 stdin、丟 Python 用 regex 找 secret pattern、找到就 exit 2 擋掉。
程式碼就像圖片中那樣,如果你看不出問題,那就跟我昨天晚上一樣。
AI 審 AI,抓出 injection
我做完第一輪 review 的時候其實沒發現問題,畢竟 Claude Code 用起來太流暢,稍微一鬆懈就可能一路 Yes 下去,但我還是依照我給自己定的規定:務必讓另一個 AI subagent 再 review 一次。
這個 subagent 吐出的話一開始我還沒警覺到,直到我讀完了整段再重新看一次的時候才嚇掉一身的貓毛:
「這個 heredoc 用的是 <<PYEOF 而不是 <<'PYEOF'(沒有單引號),會讓 bash 先做變數展開。然後 """$FILE_CONTENT""" 直接把檔案內容插到 Python 字串裡 —— 如果檔案內容是 """; import os; os.system('rm -rf ~'); """,Python 會把它當成真的程式碼執行。」
翻譯成人話就是:這個 hook 原本是設計來組擋惡意內容的,結果它自己就是惡意內容執行的入口!!!
Claude 寫一個檔案,內容有特定字串,hook 為了檢查這個字串,反而把字串當成 Python 程式執行了。
這是教科書級別的 code injection!!!
更恐怖的是 Claude Code 寫出來的一共有 5 個 hook 都用了同樣的模式,其中 audit-log.sh 裡就有 2 個 heredoc 都中招了。
全部掃完加起來一共 10 個注入點,全部都是 AI 寫的,全部都差點 push 到 GitHub 😔
正確的寫法長這樣
修法其實很簡單,但你要知道兩件事:
① heredoc 要加單引號
`<<'PYEOF'` 跟 `<<PYEOF` 差一個引號,行為完全不一樣!
沒引號 → bash 會先展開 `$變數`,然後才丟給 Python。
有引號 → bash 完全不動這坨文字,原封不動交給 Python。
② 變數要用環境變數傳,不要字串來插值
差別在哪?
字串插值 = 把使用者的輸入變成程式碼的一部分。
環境變數 = 把使用者的輸入變成資料,程式用 API 去讀。
這跟 SQL injection、XSS、command injection 一樣的道理:絕對不要讓使用者資料跟程式碼混在一起。
我以為這種基本觀念 AI 會懂,結果 Claude Code 寫出來得就是字串插值的版本。
Vibe Coding 的三條保命須知
這次事件讓我把過去 Vibe Coding 的心得濃縮成三條,分享給你。
須知①:永遠懷疑選項的正確性
Claude Code 每次要執行敏感操作,像是跑 skill、寫檔案、執行指令時,都會彈確認視窗:
Do you want to proceed?
❯ 1. Yes
2. Yes, and don't ask again for this project
3. No
我自己是很容易手滑選 2,因為我不想每次都被問,然後就會後悔。
我給自己的防呆規矩是:
第一次用的 skill、hook、agent,永遠選 1。
用過三次確認它行為可預期,才升級成 2。
這多出來的 3 秒鐘,就是你能攔下 AI 亂搞的時刻。
須知②:讓 AI 審 AI
一個 AI 寫的 code,用另一個 AI review。
我今天用的方法很土砲!
Claude Code 寫完 hook,開另一個 subagent(@schema-reviewer 模式)把 hook 丟給它,問「找出所有的 security 風險」。
然後它抓到了 RCE,我沒抓到。
我自己當然有錯,因為我應該一行一行看仔細的,但對 AI 來說「寫 code 的腦袋」跟「挑毛病的腦袋」用的是不同的 context、不同的 prompt。
同一個 AI 在同一個 session 裡自己 review 自己,它會有 bias 的現象,覺得「我剛寫的應該沒問題」。
換一個 session,或換一個 agent ,或換一個角度,它才抓得到。
就跟自己在寫書一樣,你寫的書自己一校二校三校都找不到錯字,別人卻一秒就能看到😂
須知③:commit 但不 push
我在 CLAUDE.md 裡寫了一條硬規則:Claude can `git add` and `git commit`, but never `git push`. Push is a human-only action.
為什麼?
因為 commit 是本地的,可以 reset;push 是公開的,爬不回來。
今天如果我沒這條規則,那些有 RCE 漏洞的 hook 會直接上 GitHub。萬一 repo 是 public 的,任何人 clone 下來跑 Claude Code,都可能被我的 hook 攻擊。
「push 是人類才可以進行的操作」這幾個字,今天救了我。
給還在觀望 Vibe Coding 的你
我知道這篇讀起來有點嚇人,AI 寫的 code 有漏洞、差點上 production。
但我寫出來不是要勸退你,恰恰相反,因爲我一個上午做完了過去需要一週的工作量。7 個 ADR、20 幾個檔案、完整的 project scaffold。
但「AI 幫你做事」不等於「AI 幫你做對事」。
這兩者之間差的就是這三條紀律:
① 永遠懷疑選項的正確性,不要手滑選「永遠允許」
② AI 審 AI,寫 code 的跟 review 的要分開
③ commit 不 push,最後一道防線永遠是人
我會繼續用 Claude Code 做這個專案,但我不會把它當「自動駕駛」,它只能是副駕駛,而方向盤必須牢牢在我手上。
額外收穫
昨晚的漏洞,後來變成我最好的 Demo 素材之一。中午跟客戶 demo 這個專案的時候,原本想秀架構、秀 ADR、秀那些華麗的檔案結構。
後來我改了策略,直接把昨晚的這個意外講給客戶聽。
客戶的反應超預期!
他說:我找過其他 AI 開發的同業,他們都說『AI 很強、什麼都能做』。妳是第一個告訴我『AI 會出錯,而我有自我規範去抓錯』的人。
揭露了 AI 的缺陷,反而建立了更高的信任。
這就是 Vibe Coding 的第四條隱藏須知:別賣「AI 多厲害」,要賣「我怎麼管 AI」。
前者賣的是商品,後者賣的是專業。
#但我還是很悔為什麼第一時間我自己沒有發現問題呢?
#有問題的是圖片中的第三行指令
本文原發表於 2026/04/23 的 Facebook 貼文,原文照登,僅調整網頁排版;文中提及的產品、價格與活動以當時為準。
延伸學習
HE201|Harness Engineering System Design(6 小時)
六小時的實作課:從 Blueprint 走到可以跑的規格,再用 No-code、n8n 低程式碼與程式碼三條路各做一次同一個 harness,最後處理可靠度——重試、錯誤處理、人工覆核。7 章 54 課,含常見坑與排錯、Capstone 實作,附學員講義 PDF。
NT$ 5,999
ChatGPT 很強,但真正讓你下班的是 Google
六小時完整實錄。從「AI 很厲害,為什麼你還是每天加班」這個問題出發,把 Google Workspace 當成真正的工作平台重新設計一次流程 ── Sheets 的資料結構、Drive 與 Docs 的文件流、Gmail 與 Calendar 的通知系統,再用 Apps Script 讓它自己跑起來,最後收斂成一張屬於你自己的 AI 工作能力地圖。
NT$ 4,599

