用 AI 做網站或產品,你有考慮到資安風險嗎?
文 / Coolkid發布:2026-08-19閱讀約 10 分鐘

短答:AI 寫出來的程式碼不一定安全。我做了兩個網站(Coolkid AI Lab 跟另一個會員制工具站),前後被掃出超過 30 個資安漏洞。這篇挑 6 個最有代表性的講,從「以為有防護其實沒有」到「付費內容任何人都能讀」到「一個看不見的字元就讓密鑰失效」。最後介紹 Claude Code 官方的資安掃描指令跟 OpenAI Codex 各自怎麼掃,能抓什麼、不能抓什麼。
先講結論:問題不是 AI 寫的程式碼特別爛。
問題是你覺得「能跑就沒事了」。
我也是。程式會動、頁面有出來、後台登得進去,就覺得完成了。
直到有一天跑了 Security Review,才發現一堆門根本沒鎖。
第一類:你以為有防護(其實沒有)
這類最可怕,因為你真的以為自己是安全的。
故事一:裝了 30 個安全掃描,全部沒有啟動。
我裝過一組工具,其中有 30 幾個自動掃描的 hook(就是「每次你做某件事的時候,自動幫你檢查一下」的機制)。裝完之後心裡很踏實:密鑰掃描有了、程式碼審查有了、每次送出前都會自動檢查。
幾個月後我才發現:設定檔放錯位置了。
那 30 幾個 hook 從頭到尾一次都沒有跑過。
怎麼確認的?其中一個 hook 照理說每次跑都會寫一行紀錄到 log 檔。那個檔案不存在。不是空的,是根本沒有被建立過。
教訓:「設定存在」不等於「功能運作」。驗證的方式是去看有沒有留下副作用(log、通知、實際擋住某個操作),不是看設定檔有沒有在那裡。
故事二:限流機制,每次重新啟動就歸零。
我的網站後台有 API,設了限流:同一個 IP 一分鐘只能打 30 次。聽起來很合理。
問題是:計數器存在程式的記憶體裡。我的網站跑在 Vercel(一種雲端服務),每次有新的請求進來,Vercel 可能開一個全新的程式副本來處理。
新的副本,計數器當然從零開始。
所以攻擊者只要每次碰到不同的副本,限流就形同虛設。文件上寫著「30 次/分鐘暴力破解防護」,實際在正式環境完全沒有生效。
同一個模式:看起來有防護,但從來沒有在真實環境驗證過。Security Review 工具不一定能抓到這種,但工具會問你「這個計數器存在哪裡?重啟之後還在嗎?」——光是這個問題就值了。
第二類:你以為別人看不到(其實全都看得到)
故事三:付費內容,任何人都能讀。
我的另一個網站有付費會員區,付了錢才能看完整文章。前端做得很到位:沒登入就顯示「請先加入會員」,登入了但不是付費會員就顯示「升級方案」。
問題是:這個「擋」只發生在前端(就是你的瀏覽器上)。
後端的資料庫呢?沒設任何限制。有人只要直接對資料庫發一個查詢,所有付費文章的完整內容就全部回來了。
用生活比喻:我在門口放了一個寫著「會員專用」的立牌,但門沒有鎖。你不用從門口走,繞到後面窗戶就進去了。
後來修的做法是:在資料庫層加上權限規則,不管你從哪裡查詢,沒有對應的會員身份就是讀不到那個欄位。
故事四:網頁標題沒有跳脫,可以被注入程式碼。
這個我完全不知道自己犯了。
我的網站用一套自己寫的產生器,每篇文章的標題會被自動填進網頁的 <head> 區塊(就是瀏覽器分頁上顯示的那個文字)。
問題是:標題的內容是直接塞進去的,沒有經過「跳脫」處理。跳脫的意思是把特殊符號(像 < > ")轉成無害的格式,讓瀏覽器當成純文字顯示,而不是當成程式碼執行。
如果有人能把一段惡意程式碼放進標題欄位,瀏覽器會把那段程式碼跑起來。
這就是 XSS(Cross-Site Scripting,跨站腳本攻擊)。名字聽起來很專業,白話就是:你的網頁不小心讓別人的程式碼混進來跑了。
「看不到」跟「拿不到」是兩件事。前端隱藏 ≠ 後端保護。資料的權限要在資料庫那一層設,不能只靠前端畫面擋。跳脫處理要在輸出那一層做,不能假設輸入一定乾淨。
第三類:你根本不知道有問題
故事五:Python 程式碼默默吞掉錯誤,差點刪掉別人的登入。
這個最難解釋,但也是 AI 寫程式碼最常見的問題之一。
我的後台有個「登出所有裝置」的功能。功能會去資料庫撈出你所有的登入紀錄,然後逐筆刪除。撈的過程會分好幾批回來。
AI 寫的程式碼裡有一行:keys = res[1] or []。白話翻譯是「把撈回來的結果存起來,如果是空的就當成空清單」。
問題出在 Python 的 or:這個寫法不只把「空的」當成空的。{}(空字典)、""(空字串)、0、False,這些全部都會被當成「空的」,然後被默默換成一個正常的空清單。
所以如果資料庫回傳了一個畸形的回應(格式壞掉了),程式不會報錯,而是假裝沒事繼續跑。
最糟會怎樣?第一批正常回來了一筆登入紀錄,第二批回來一個格式壞掉的東西,程式當成「掃完了,只有一筆」,直接把那一筆刪掉。實際上可能有三筆,但另外兩筆因為畸形回應被跳過。
故事六:密鑰多了一個看不見的換行,debug 兩小時。
我在設定寄信服務(Resend)的 API 密鑰時,複製貼上到 Vercel 的環境變數裡。結果一直報「密鑰無效」。
密鑰是對的。字元完全正確。
花了快兩小時才發現:複製的時候尾巴多帶了一個換行字元。這個字元在畫面上完全看不到,但送出去的時候就變成了一個錯誤的密鑰。
修法很簡單:程式碼讀到密鑰之後加一行 .strip()(去掉頭尾的空白跟換行)。但在那之前,API 回給你的錯誤訊息跟「密鑰真的打錯」是一模一樣的。
AI 寫的程式碼有個通病:在理想情況下表現完美,但遇到意外輸入就默默出錯而不是大聲報錯。工程師把這個叫做「fail open」(壞了就放行),正確的設計是「fail closed」(壞了就擋住)。你不用記術語,但記住這個直覺:程式碼遇到看不懂的東西時,應該停下來喊救命,不是假裝沒事。
兩個免費工具怎麼幫你掃?
上面 6 個問題,我不是自己讀程式碼找出來的。很多是跑了 Security Review 工具之後才知道的。
目前我用過兩個:Claude Code 的 /security-review 跟 OpenAI 的 Codex。兩個都是 AI coding agent,跟一般的聊天機器人不同:能自己讀你整個專案、自己找檔案,不用你手動挑程式碼貼過去。不用額外付費(前提是你已經有 Claude Code 或 ChatGPT Pro 的訂閱)。
Claude Code 的做法
Anthropic 官方開源了一個專門的資安掃描指令叫 /security-review。跟自己隨便問一句「有沒有漏洞」不一樣:裡面有一張完整的漏洞清單逐項掃(SQL 注入、XSS、權限繞過、密鑰外洩……),每條結果附信心分數,太可能是誤報的直接過濾掉。這個指令甚至可以設成 GitHub Action,每次推程式碼都自動掃。
我的經驗:上面故事二的 XSS 跟故事一的限流問題,都是第一輪掃描就抓出來的。這工具特別擅長抓「你該跳脫但沒跳脫」跟「你該驗證但沒驗證」這兩類。
最快的方式是打開 Claude Code,直接貼這句:
幫我用資安的角度從頭到尾審一遍這個專案的程式碼,每個有風險的地方列出來,標明嚴重程度(CRITICAL / HIGH / MEDIUM)和修法建議。
Claude Code 會自己讀你專案裡的檔案,跑完列一張清單,照嚴重程度排好。每條告訴你問題在哪個檔案哪一行、具體的攻擊情境、跟修法建議。
想要完整版的結構化掃描,可以裝官方的 /security-review 指令。GitHub 搜 anthropics/claude-code-security-review,照說明裝好之後打 /security-review 就行了。(第一次用 GitHub?可以先看這篇教學。)
Codex 的做法
OpenAI 的 Codex 也是一個 AI coding agent,跟 Claude Code 一樣能讀你整個專案的程式碼。差別在於 Codex 沒有專門的資安掃描指令,你直接用白話告訴它「幫我掃資安」就好。
使用方式跟 Claude Code 不太一樣:你把 GitHub repo 連上去,開一個新任務,Codex 會在雲端的隔離環境裡跑。不是即時對話,比較像交作業,過一陣子回來看結果。
開一個新 task,貼這段當任務描述:
請用資安專家的角度從頭到尾審一遍這個 repo 的程式碼。每個有風險的地方列出來,標明:
1. 嚴重程度(CRITICAL / HIGH / MEDIUM / LOW)
2. 問題在哪裡(檔名和行號)
3. 為什麼這是問題
4. 怎麼修
因為 Codex 也能讀你的檔案結構,不用像聊天機器人那樣自己挑程式碼一段一段貼。但沒有 Claude Code 那套結構化的掃描流程跟誤報過濾,掃出來的品質不一定每次都穩定。
這兩個工具抓不到什麼?
說實話,不少。故事一的「30 個 hook 裝錯位置」,工具抓不到,因為程式碼本身沒問題,是設定檔的路徑不對。故事六的「密鑰多了換行」,工具也不一定抓得到,因為密鑰的值在程式碼裡看不到。
簡單說:工具擅長抓程式碼層面的漏洞(少了跳脫、少了驗證、少了權限檢查),不擅長抓環境設定跟部署流程的問題。
但光是前者就夠用了。我的 30 幾個漏洞裡面,超過一半是程式碼層面的,工具一掃就出來。
寫完程式碼之後,多做一件事
這篇不是要你學會資安。
是要你知道:用 AI 寫程式碼的時候,「能跑」跟「安全」是兩件事。AI 不會主動告訴你「這段我寫的有資安風險」,就像不會主動告訴你「這段我瞎掰的」一樣。
你不需要看得懂每一行程式碼,但你可以做一件事:寫完之後,請另一個 AI 用資安的角度掃一遍。
30 秒的事,可能幫你擋掉一個你根本不知道存在的漏洞。
AI 寫出來的程式碼不一定安全。我做了兩個網站,前後被掃出超過 30 個資安漏洞。本篇挑 6 個最有代表性的講:裝了 30 個安全 hook 全部沒生效(設定檔放錯位置)、限流計數器存在記憶體裡每次重啟歸零(雲端環境等於沒設)、付費內容只在前端擋後端沒擋(直接查資料庫就全部看到)、網頁標題沒跳脫可以被注入程式碼(XSS)、Python or [] 把畸形回應默默吞掉差點刪錯登入、API 密鑰複製貼上多了看不見的換行字元。Claude Code 的官方 /security-review 指令跟 OpenAI Codex 都能做資安掃描。前者有結構化的三階段流程跟誤報過濾,後者是通用 agent 用白話請求掃描。兩者都擅長抓程式碼層面的漏洞(少了跳脫、少了驗證、少了權限檢查),不擅長抓環境設定跟部署流程的問題。
名詞解釋
- hook(掛鉤)
- 在工具的固定時機(開始對話、寫完檔案、結束回合)自動執行你指定動作的機制。像是幫 AI 設「進門要換鞋」的家規,設一次每次都自動生效。
- API(應用程式介面)
- 程式跟程式之間溝通的窗口。例如你的程式透過 LINE 的 API 自動發訊息、透過 Google 的 API 讀試算表。
- 內容安全政策(CSP, Content Security Policy)
- 網站的白名單防火牆:只允許指定來源的程式跟資源執行,用來擋惡意注入。設太嚴會誤殺自己要用的工具。
- Vercel
- 把網站免費發佈到網路上的服務:接上 GitHub 後,每次推程式碼就自動更新網站,個人專案免費方案就夠用。
相關文章
▸ 常見問題
q
a
q
a
q
a
q
a
看完這篇之前先確認:
- 用 AI 寫了程式碼,但從來沒想過「安全」這件事的人
- 想知道 Claude Code 或 Codex 的資安掃描能幫什麼忙的人
- 正在用 AI 做網站或自動化工具,想確認有沒有明顯漏洞的人
- 找企業級滲透測試或資安認證教學的人(這篇是個人實作,不是專業資安)
- 還沒開始用 AI 寫程式的人(先看「AI Agent 是什麼」那篇)
- 想學特定攻擊手法的人(這篇講的是怎麼被掃出來,不是怎麼攻擊)
