寫完監控和評分那幾篇後,我心血來潮給系統做了一輪安全審查。想像中的產出是「檢查完畢,體質良好」,實際的產出是一份讓我不太想給人看的清單:最大的幾個漏洞,全部是我自己親手埋的。
沒有駭客、沒有 0-day、沒有供應鏈攻擊。就是一個知道所有最佳實踐的工程師,在「反正是自己家的系統」的心態下,把上班時絕不會犯的錯,在家裡犯好犯滿。
今天這篇是自白書。三個真實的錯誤、它們為什麼會發生、怎麼修,以及幾條通則。先說好:本篇講的是原則和錯誤模式,現存系統的具體配置不會出現在文章裡——這本身就是其中一條原則。

審查的第一站是 workspace 的 git 狀態。一跑 git ls-files,心涼了半截:一份 API 憑證的 JSON 檔,安安穩穩地躺在版本控制裡,跟著每一次 commit 被完整保存。
它怎麼進去的?回憶起來平淡無奇:某天為了讓 Agent 串接外部服務,把憑證檔放進 workspace(因為容器掛載的就是這個目錄,放這裡最方便);某天想給 workspace 上版本控制,git add -A 一把梭;憑證就這樣入庫了。兩個「當下都合理」的動作,交叉出一個漏洞。
修復比想像中麻煩,因為 git 的歷史是永久的——把檔案從最新 commit 刪掉毫無意義,任何人翻歷史都撈得回來。完整的處置是三步:
# 1. 讓 git 忘記它(但保留本機檔案)
git rm --cached credentials.json
echo "credentials.json" >> .gitignore
# 2. 清洗歷史(用 git-filter-repo 或 BFG 重寫所有 commit)
git filter-repo --path credentials.json --invert-paths
# 3. 最重要的一步:把這份憑證「作廢重發」
# ——歷史清洗只能防未來,你必須假設它已經洩漏
第三步是多數人會偷懶跳過的:**只要憑證曾經進過版本庫,就當它已經洩漏,撤銷重發。**清洗歷史是打掃現場,換鎖才是止損。
第二個發現在 git remote -v 的輸出裡:remote URL 長這樣——
https://<username>:ghp_xxxxxxxxxxxx@github.com/...
一個 Personal Access Token,明文嵌在 URL 中。這是很多教學文章教的「免輸入密碼」快捷法,方便到令人上癮。問題是這個 URL 會出現在 .git/config(明文檔案)、shell 歷史、任何 git remote -v 的輸出——包括你截圖貼文、錄影 demo、把 log 貼給別人 debug 的時候。而我的 workspace 又被同步工具複製到多台機器,等於每台同步節點上都有一份明文 token。
修法是換掉認證通道,讓 URL 裡不再有秘密:
# 改用 credential manager 保管(或改走 SSH key)
git remote set-url origin https://github.com/<user>/<repo>.git
git config credential.helper manager # token 進系統的憑證保險箱
# 然後:舊 token 撤銷重發(理由同上——它已經到處都是了)
第三個最難堪。全文搜尋 workspace 裡的敏感關鍵字(password、token、secret……),在某份服務筆記裡撈到一行:「管理介面密碼:XXXX」。
為什麼致命?因為這套系統的核心設計就是「所有 Markdown 都會被 LLM 讀取」。筆記是 Agent 的記憶、會被 dreaming 整合、會被同步到多台裝置、片段可能被引用進報告——甚至被我複製貼上進這個系列的草稿。在傳統筆記軟體裡寫密碼只是壞習慣;在 Agent 系統的 workspace 裡寫密碼,等於把密碼放進一條你無法完全預測的資料流。
修復動作:改密碼、筆記改寫成「密碼在密碼管理器,條目名 XX」。真正的秘密只活在兩個地方——密碼管理器,或部署層注入的環境變數(Day 19 講 HA token 時用過的做法)。LLM 可讀層裡只放「指標」,不放「值」。
| 錯誤 | 表面原因 | 真正根因 |
|---|---|---|
| 憑證進 git | git add -A |
憑證和資料放在同一個目錄層 |
| PAT 進 URL | 教學抄來的快捷法 | 圖方便,沒想過 URL 是明文配置 |
| 密碼進筆記 | 隨手記 | 沒意識到「筆記」在這系統裡是資料流 |
共同點是:每個錯誤在犯下的當下都毫無感覺,因為家用系統沒有 security review、沒有掃描 pipeline、沒有同事的白眼。企業環境靠制度擋掉的東西,個人環境只剩你的習慣——而習慣在「就自己用」的心態下最容易鬆動。事實上我的 workspace 根本不是「就自己用」:它同步多台機器、對外開了 Web 介面、每天被 LLM 讀寫。攻擊面早就是分散式系統等級,防護心態還停在單機。
再誠實一層:「反正是私有 repo」是這一切最好的安眠藥。倉庫私有、機器自己的——所以憑證檔先放著、歷史殘留以後再清,「先隨便弄,後面再慢慢搞」。這個心態的問題不在當下(私有 repo 確實沒別人看得到),在它假設了「以後」真的會來:等你想清歷史的那天,那把金鑰已經跟著同步工具住進每一台機器、跟著備份躺在你早就忘記的角落。私有降低的是被看見的機率,不是擴散的速度。
對標我現在的管理辦法,同一件事長這樣:
.gitignore 擋版本庫、同步工具的排除規則擋擴散——它們互相獨立,設了一個不會自動有另一個(下一段那個盲區就是這麼來的)從「先隨便弄」到這五條,中間隔的不是技術,是三次被自己嚇到。
發布任何內容前,另有一道機敏清單把關(這個系列每篇文末的 checklist 就是它)——資安不是狀態,是重複執行的動作。
而上面第三條那道例行掃描,後來又補了我一課。它最初只掃 git 追蹤的檔案——聽起來合理,掃版本庫嘛。結果幾份含舊憑證的檔在磁碟上躺了兩個月沒人發現:被 .gitignore 擋在版本庫外的檔,恰好也被掃描器擋在視野外——擋住 git 的那條規則,同時讓警察看不見它。而同步工具不讀 .gitignore,那些檔照樣被複製到每一台機器。.gitignore 和同步排除規則是兩道各自獨立的閘門,「git 裡看不到」跟「沒有外流」是兩件事。現在掃描器連未追蹤檔一起掃——**防線的盲區,往往正好在另一道防線的陰影裡。**順帶一提,這輪審查用到的工具毫無高深可言——git ls-files、git remote -v、全文關鍵字搜尋,三個指令就挖出三個洞。挖洞的門檻從來不高,高的是願意對自己系統動手的自覺。
三條通則帶走:秘密永遠不進版本庫(進過就作廢重發)、秘密不進 LLM 可讀層(只放指標不放值)、以及——用審查對抗心態,因為「自己家的系統」四個字就是最大的漏洞。
自白完畢,明天回到建設性的主題:MCP Server 工具層。在桌面 AI 輸入一句「重啟 CLI 容器」,NAS 上的 docker restart 就自己跑完了——這中間發生了什麼,以及哪些操作我刻意「不」做成工具。
🔑 這篇的關鍵字
秘密管理:只進環境變數 /.env+.gitignore,不進版本庫、不進 LLM 可讀層
LLM 可讀層只放指標不放值(例:記憶檔寫「token 已輪替」,不寫 token 本身)
外洩後的正確順序:先撤銷再清理——git history 清乾淨了,外流的那把鑰匙還是有效的
防線的盲區在另一道防線的陰影裡:.gitignore擋住的檔,掃描器也看不見,但同步工具照搬——掃描要含未追蹤檔
權限按破壞半徑分級:唯讀 / 可寫 / 可刪 / 可改設定,不是一把 admin 走天下
我是一名金融業資訊工程師,這是我半年來在家自架 AI Agent 系統的實錄。