在你開始寫程式碼之前
我有幾句話要先說
可能會相當嚴厲
但請聽我把真心話講完

接下來我會說一段不太溫柔、而且可能有點居高臨下的話。不過如果你願意把話聽完,我想你也會理解這些嚴厲話語背後的原因。先跟你道個歉,請原諒我這種囂張的口吻。
在我對你說這些之前,先讓我談談圍繞這個產業的一些氛圍。軟體業界長久以來存在一些不易消失的風氣:
「賣得好的產品就是對的」
「品質?只要沒發生故障就好」
「細節交給供應商處理沒問題」
作為在商業現場求生的折衷,這種想法可以理解。但從工程師的職業倫理來看,這實在難以接受。試想一個建築師說「只要房子不倒塌,裡面的構造怎樣都無所謂」,你願意住在他蓋的房子裡嗎?
現在又遇上了生成式 AI 帶來的「vibe coding(憑直覺快速寫碼)」浪潮。
「我這個 IT 外行只花一週就做出某某應用程式!」
「過去要花 100 小時的工作,現在只要 5 小時就自動化完成!」
這種驚訝感不完全是壞事。它很棒,是走進工程世界的良好入口。分享到 X(前 Twitter)或拿去跟人炫耀都沒問題。
只是,請千萬不要把那種程度的東西直接拿去正式上線。
我能理解商務端的心情。人人都能寫軟體的這千載難逢的機會,誰不想把握?但為了兼顧兩邊,把事情做到安全且負責任,這篇文章提供最低限度的指引。
如果你做的應用程式導致某人的信用卡資訊外洩,或私人照片被公開,「不好意思,這是 AI 寫的程式碼」這句話是說不通的。無論是在法庭上、在 X 上,或在自己良心面前,都沒用。
安全性絕對不能妥協。不能,也不該。
不要直接動用 AWS、GCP、Azure 之類的雲端基礎設施。那些是給專業人士用的工具箱。很方便,但一不小心就會傷手。
只有完全理解那些陷阱的人,才應該使用 IaaS。「完全理解」大概代表你能用自己的話說出 AWS Well‑Architected 的基本要點,並能講出安全群組、IAM、網路設計常見的陷阱。
「那 Vercel 或 Firebase 可以嗎?」——很抱歉,還是太早。
例如 Firestore 的安全規則,在選擇測試模式(test mode)時,預設幾乎是全部允許。直接這樣上線,只要稍微改變 URL 就可能看到別人的資料。Supabase 的列級安全(Row Level Security)也存在相同問題。「能登入」跟「不能看到別人的資料」是完全不同的問題。
跟 IaaS 比起來,PaaS 要注意的事情少很多,但仍需讀懂 PaaS 提供的安全指南,並多次用實驗性應用去檢驗該服務的陷阱再使用。做不到的話,還是不要上線。
那應該怎麼做?答案是依賴像 Lovable、Bolt.new 這類更上層的 SaaS。這些平台把認證、資料庫、主機託管等預設為「偏安全的預設值」來幫你處理。
不過 SaaS 也有陷阱要注意:
做不到上面這些,就不要上線。
即便在 SaaS 層,也不會把祕密管理當成魔法自動解決掉。這一塊如果處理草率,後果最嚴重。
「因為是 SaaS 所以安全」並不是「SaaS 會替你管理所有祕密」的意思。祕密放在哪、誰能接觸、若外洩如何阻止,這些最後都是你的責任。
有人在做完登入功能會誤以為「安全做好了」。不是的,那只是入口鎖上而已。能否進到系統內卻看不到別人的房間,完全是另一回事。
舉例來說,你可以透過 https://myapp.com/orders/12345 看見自己的訂單。那如果把 12345 改成 12346,會不會跑出其他人的訂單?這就是所謂的 IDOR(Insecure Direct Object Reference)。在 OWASP 的弱點排行中,它通常都名列前茅,是一種典型事故。
防範的做法只有一件事:
每次取出資料時,伺服器端都要檢查「這筆資料,真的屬於現在登入的使用者嗎?」
別抱著「URL 有 ID,應該只有本人會看到」的天真想法。請注意,當你叫 AI 寫「取得訂單的 API」時,AI 很容易忘記這種檢查。務必 review、一定要。
使用者輸入、外部 API 回傳、上傳的檔案——這些都可能是敵人。Web 世界不該有太多性善說。
「在表單做了驗證就沒問題」這句話騙不了人。
瀏覽器端的檢查(Client‑side validation)只是為了 UX,不能當成安全防線。打開開發者工具,任何人都能在幾秒鐘內把 JavaScript 關掉或直接改寫 HTTP 請求。無論你在 UI 上限制「年齡必須 ≥ 18」「只能輸入數字」「最多 100 字」,只要在伺服器端沒有做相同檢查,那都無效。驗證務必在伺服器端也做一次。
特別是檔案上傳,事故頻發:
../../etc/passwd 類似的相對路徑逃脫(路徑穿越)如果只是想「先弄個上傳功能」,用 SaaS 型建置平台提供的預設機制是最安全的。不要自己硬做。
AI 會很乾脆地說「用這個就可以了」。但那個套件真的能信嗎?最後更新是什麼時候?維護者是誰?
AI 有時會大方地編造不存在的套件名稱(幻覺),或推薦五年前就停止維護、充滿漏洞的套件。最惡劣的情況是,攻擊者會利用 AI 常犯錯的套件名(typo squatting)上傳惡意程式。
在加入第三方套件前,至少要做這些檢查:
package-lock.json 或 requirements.txt 鎖版本相依套件就是你把工作交給的「外包」。不要把工作交給素行不明的外包方。
AI 寫的程式常常在發生錯誤時把完整的錯誤訊息(stack trace)直接回給使用者,這是非常危險的。
對攻擊者來說,這些就是地圖。在正式環境,對使用者只回應「處理失敗」這類抽象訊息,把細節寫入伺服器端日誌。大部分框架都支援「開發模式」與「正式模式」切換,記得先確認。
如果你在做內部系統,可能會想:「沒對外公開,應該不需要太注意安全吧。」
這樣的想法會觸發事故。
原因有四個:
即使做了安全措施,單靠那些還不夠。沒有把發生的事記錄下來並定期檢查,你甚至不會知道自己被入侵了。
現實情況通常是:
「我的應用很小不會被攻擊」這種想法不通。很多攻擊是自動化的,會無差別掃描。只要發現脆弱系統就會被利用,不看規模大小。
至少要做的有:
日誌只有在事後才有用,因此務必在還沒事前就開始記錄。「出了事再去記錄」那時候就太晚了。
當你在睡覺時,雲端帳單可能正在爆表。
「用多少付多少」的商業模式如果沒先估算使用量會變成無底洞。實作前至少要確認:
「第一次設定好了就沒事」這種想法不行。使用方式一變,成本也會跟著改變。
在你高興地說「跑起來了!」的同時,計價的表正在不停轉動。
在開始寫程式前,花五分鐘想清楚:
「我不知道」在法律面前不是藉口。若造成損害賠償還算幸運,可能還會涉及刑責或行政罰。
下面的內容只給那些要做「非一次性」應用的人看。
如果你週末做一個自用、小玩具,週一就丟掉,那到此為止就好。但若是要被別人使用、明天還要跑、下個月還會有人用的應用,接下來的內容才是真正重點。
這是軟體開發中最重要的真理之一。請記住:
程式碼的 bug 可以修。
資料結構的技術債,事後付款會帶利息。
具體來說:
所以在開始寫程式之前,資料設計要先確認:
若事後必須改資料結構,至少遵守:
這是 AI 寫的程式裡常見的事故來源。
以付款流程為例:「扣使用者餘額」「把商品庫存減少」「建立訂單紀錄」──如果在執行到第二步時停電,會發生什麼?錢被扣了但商品沒出貨怎麼辦?
有兩個概念可以避免這種情況:
「按同一個按鈕按兩下造成雙重訂單」「付款 API 超時後重試導致雙重收費」─ 這些事故若沒考量上面兩點就一定會發生。當你請 AI 寫流程時,要問:「如果途中失敗會怎樣?」「被呼叫兩次會怎樣?」並把這些場景 cover 起來。
AI 若只被告「寫測試」通常只會產出快樂路徑(happy path)的測試;若要全覆蓋會濫用 mock,產出沒意義的測試。為了讓測試有意義,不如把工作拆成步驟來做。
流程建議:
AI 生成的測試一定要自己讀。測試就是文件。讀不懂就要叫 AI 把測試項目說明清楚。
test_1,要像「訂單金額為 0 時拒絕訂單」三週後的自己就是陌生人,三個月後更是了。
「昨天還能跑,今天不行」——只有 Git 能救你。不管你用不使用 Lovable、Bolt 等 SaaS,都沒例外。
.gitignore 絕對不要把祕密(API 金鑰、環境變數檔)提交到 repo只做這些,開發的安心感就會提升十倍。
絕對不要把「在正式環境試一下」當成習慣,那是 99% 的事故起點。
至少把「開發」與「正式」分開,資料庫也要分。誤刪正式使用者資料不是笑話。
這個應用會有多少人使用?資料會累積到多少筆?一天會被呼叫幾次?
不需一開始把系統做得完美,但請對你現在寫的程式大略有個承載界限的概念。知道能撐到多少筆資料,就能預防很多事故。
最後這一條或許是最重要的。
軟體工程這領域半個多世紀以來,累積了無數失敗與從失敗中得出的智慧。版本控制、測試、CI/CD、程式碼審查、設計模式、SRE、資安最佳實務——這些都是有人吃過苦頭才建立起來的經驗。
你不需要重複別人的錯誤。可以事先讀書或研究真實的事故案例。不是叫你全部讀完,只要挑你有興趣或相關的部分看就好。沒有必要再勤懇地掉進前人已經踩過的坑。
即便如此,你還是會犯錯。重要的是犯錯後怎麼做:
比起失敗本身,失敗之後的處理更決定長期成效。
這不是用來當閱讀材料的文章,而是給你向 AI 提問時的「索引」。
沒有這些也不代表做不了東西。但有了這些觀點,你在看到 AI 的回覆或程式執行結果時,就會知道該看什麼、怎麼處理。
下面以專業觀點列出可用來問 AI 的關鍵字。使用方式:
不必全部理解。今天挑 2~3 項,明天再學其他。這樣慢慢累積你的武器庫。
大分類一覽
設計審查會看的觀點
程式碼審查會看的觀點
A-1. 架構風格
A-2. 領域建模(Domain Modeling)
A-3. 模組切分與依賴關係
B-1. 資料建模
B-2. API 設計
B-3. 一致性與交易
B-4. 非同步處理(Queue / Event)
B-5. 快取(Cache)
C-1. 使用者研究
C-2. 資訊架構(Information Architecture)
C-3. 互動設計
C-4. UX 原則與啟發式
C-5. 可及性(UX 面)
C-6. UX 指標
D-1. 可擴展性(Scalability)
D-2. 可用性與韌性(Availability / Resilience)
D-3. 可觀測性(Observability)
D-4. 環境與基礎設施設計
D-5. 資料遷移
E-1. 安全原則
E-2. 資料保護與多租戶
F-1. 視覺設計原則
F-2. 設計系統
F-3. 元件設計
F-4. 樣式
F-5. 狀態管理
F-6. 前端效能
F-7. 可及性(實作面)
F-8. 動畫與互動
G-1. 設計原則
G-2. 設計模式(GoF)
G-3. 企業級模式(PoEAA 等)
H-1. 乾淨程式碼(Clean Code)
H-2. 重構(Refactoring)
H-3. 型別設計與契約
H-4. 函數式編程思維
H-5. 錯誤處理
I-1. 測試策略與哲學
I-2. 測試類型(功能面)
I-3. 測試類型(UI / 視覺)
I-4. 測試類型(契約 / 邊界)
I-5. 測試類型(非功能)
I-6. 測試替身(Test Double)
I-7. 測試設計技法
J-1. 並行處理與多線程
J-2. 效能
SELECT *(只抓必要欄位)K-1. 文件化
K-2. 版本管理與開發流程
L-1. 威脅建模
L-2. 通訊保護
* 與 credentials 一起用)L-3. 加密與祕密管理
L-4. 認證與會話
exp、jti、不要放機敏資訊L-5. 授權與存取控制
L-6. 輸入驗證
L-7. 注入攻擊
L-8. 輸出編碼
dangerouslySetInnerHTML 的風險[innerHTML] 的風險javascript: / data: schemeL-9. 錯誤處理(安全面)
L-10. SSRF(Server‑Side Request Forgery)
原文出處:https://qiita.com/Akira-Isegawa/items/00f23d206c504db2ac3b