5.4 進階
安全模型
寫入 API 只接受本機連線、只能動筆記資料夾內的檔案;安裝 plugin 前會先做靜態檢查。也說明開放到區網時要注意什麼。
NoteCraftApp 會碰到你檔案系統的地方只有兩個:view 模式的寫入 API,以及 install-plugin 寫進 .notecraft/plugins/ 的檔案。兩者各有一道防線。
寫入 API 只接受本機
寫入 API(新增筆記、改標籤、刪除筆記、切換 plugin)只存在於 view 模式。serve 與 build 的產物沒有寫入 API。
每個 /api/* 請求都會檢查連線來源,不是 127.0.0.1 或 ::1 就回 403。從筆記資料夾即時送出圖片的 /notes-assets/* 也套用同一條規則。
只能動筆記資料夾內的檔案
API 收到的每個路徑都要通過三道檢查才會讀寫:
- 以
path.resolve轉成絕對路徑,消掉..之類的相對片段 - 確認結果仍以筆記資料夾的路徑開頭
- 檔案已存在時,再以
fs.realpath解開 symlink,確認實際位置也在筆記資料夾內
任何一道不過就拒絕。所以從介面送進來的 slug 或圖片路徑,碰不到筆記資料夾以外的檔案。
view 模式 收到 /api/* 請求 帶著 slug 或檔案路徑 127.0.0.1 或 ::1 /notes-assets/* 同一條規則 path.resolve 轉成絕對路徑 消掉 .. 之類的相對片段 fs.realpath 解開 symlink 實際位置也在筆記資料夾內? updatedAt 例外是 plugin 的啟用與停用:它寫的是 .notecraft/plugins.json,只動頂層 disabled 陣列,plugin id 也要符合小寫英數與 - 的格式。
排除的檔案不會進產物
被 ignore.json 排除的檔案,NoteCraftApp 從頭到尾都不讀:不產生頁面、不進搜尋索引與 /wb-index.json、資料不嵌進頁面,被筆記引用的圖片也不複製;view 的 /notes-assets/* 對它們回 404。build 結束時還會再檢查一次產物,出現被排除的檔案就讓 build 失敗,避免日後哪個環節漏掉。
開放到區網
view 與 serve 預設綁 127.0.0.1,只有本機連得到。帶 --host 0.0.0.0 會讓同一個網路裡的其他裝置都能連進來。
從其他裝置連進來時,寫入 API 一律回 403。筆記裡以相對路徑引用的圖片則看子命令:view 回 403、圖片不顯示;serve 改送上次 build 複製進產物的那份,只有被筆記引用的檔案,和部署出去的站看到的一樣。
安裝 plugin 前的檢查
plugin 是在你的 build 與瀏覽器裡執行的前端程式碼。install-plugin 在寫入任何檔案之前,先對下載到的內容做靜態檢查,有一項不過就拒絕安裝:
| 檢查 | 擋下什麼 |
|---|---|
| 路徑 | 含 .. 或絕對路徑的檔名 |
| 檔案類型 | .tsx、.ts、.json、.md、.css、.svg、.png 以外的檔案,例如 *.sh、*.mjs |
| 檔名 | 任何一層的 package.json、lockfile(package-lock.json、npm-shrinkwrap.json、yarn.lock、pnpm-lock.yaml、bun.lockb、bun.lock)、tsconfig.json、jsconfig.json。副檔名是 .json 也一樣擋(1.8.4 起;更早的版本會放行 package.json) |
| 必要檔案 | 缺 notecraft-plugin.json 或 renderer.tsx |
| import | 白名單以外的套件 |
dangerouslySetInnerHTML | 任何地方出現都擋 |
engines | manifest 要求的 notecraftapp 版本與你的不符 |
允許 import 的套件和 AI 生成元件共用同一份白名單:react、react-dom、motion、recharts、d3、lucide-react、clsx、tailwind-merge,加上相對路徑。
檢查通過後,CLI 會列出來源與所有檔案,等你輸入 y 才寫入。CI 這類非互動環境要帶 --yes 才會安裝,否則直接結束。
install-plugin 不會執行任何安裝腳本,也不會為 plugin 跑 npm install。
安裝來源與指令見安裝來源。