前言¶
DSH 的理念是「一切皆插件」,profile 用來劃分不同的插件環境。其中 safemode 的定位是“乾淨環境”:排障、做對照,或者只想要核心能力時,用它啓動最合適。
但 safemode profile 本質上就是 $DSH_HOME/profiles/safemode/ 下的一組普通文件。一次 dsh plugin --profile safemode add ...、一次手動編輯 package.json,甚至某個腳本的一次誤寫,都會讓這個環境不再幹淨,而且你不一定會立刻發現。事後逐個文件覈對、手動清理,費時也不可靠。
dsh-safemode-profile 把這件事自動化了:啓動時無條件強制還原,運行期持續守護,讓 dsh --profile safemode 在任何時刻都只含白名單核心 bundle。
這是什麼¶
dsh-safemode-profile 是一個 DSH 插件,作者 jinsiyu,MIT 許可。它只有一個職責:把 safemode profile 鎖定在白名單模板上——啓動時強制還原,運行期發現漂移自動還原。
前置要求:已安裝 DSH(@deepseek-ai/dsh)與 Node.js(≥ 18)。
核心功能¶
啓動時強制還原¶
DSH 每次啓動加載本插件時,會把 $DSH_HOME/profiles/safemode/ 無條件寫回白名單模板,涉及三個文件:
| 文件 | 強制內容 |
|---|---|
package.json |
dsh.profile.bundles 爲白名單(默認 @deepseek-ai/dsh-base + @deepseek-ai/dsh-web-app),dependencies 清空 |
cordis.patch.yml |
空的用戶 patch 層 |
pnpm-workspace.yaml |
pnpm workspace 設置 |
與模板一致時不動(避免自觸發),不一致一律重寫。
運行期雙通道守護¶
插件存活期間,用兩條通道監控 profile 是否被改動:
1、fs.watch 即時監聽:三個文件任何變更,防抖 300ms 後立即還原;
2、30 秒輪詢兜底:detectDrift 全量比對,覆蓋 watch 不可靠(如掛載場景)和文件被外部整體替換的情況。
發現漂移——bundle 被加/刪、patch 層被寫入、dependencies 被加了東西,就自動還原,並記錄 warn 日誌。
無構建腳本,一次裝好¶
包內沒有 postinstall,也沒有任何構建腳本,pnpm 不會攔截它。dsh plugin add 一次成功(退出碼 0),不需要配置 approve-builds / allowBuilds。還原與守護的全部工作由插件行在 DSH 啓動加載時完成。
白名單可定製¶
白名單是唯一的定製入口,通過環境變量 DSH_SAFEMODE_BUNDLES 設置。守護與還原讀取的是同一個白名單,改一處即全局生效。
安裝與啓用¶
先確認前置條件:已安裝 DSH(@deepseek-ai/dsh)和 Node.js(≥ 18)。下面三種方式任選其一,命令以官方文檔給出的形式爲準:
方式 A(推薦,npm 安裝):
dsh plugin --profile web add dsh-safemode-profile
方式 B(GitHub 直裝,顯式指定 main 分支):
dsh plugin --profile web add github:jinsiyu/dsh-safemode-profile#main
方式 C(本地打包 tgz):
npm pack # 生成 dsh-safemode-profile-<版本>.tgz
dsh plugin --profile web add .\dsh-safemode-profile-<版本>.tgz
裝完重啓 DSH,插件行生效後,safemode 即進入“強制還原 + 常駐守護”狀態。
典型用法¶
零第三方插件啓動¶
dsh --profile safemode
safemode 也帶 webServer(默認 3080),如果和 web profile 同時運行,建議用 --port 錯開:
dsh --profile safemode --port 3081
自定義白名單¶
比如只想留純 CLI(無 GUI):
$env:DSH_SAFEMODE_BUNDLES = "@deepseek-ai/dsh-base"
dsh 啓動時繼承該環境變量即生效。注意不要手動改 safemode 的 profile 文件,任何改動都會被守護邏輯還原,定製一律走這個環境變量。
手動強制還原一次¶
不想重啓 DSH,或者排查問題時,可以立即觸發一次還原:
node scripts/ensure-safemode.mjs
文件系統加固(可選)¶
在插件守護之外,還可以把三個受管文件設爲只讀,從文件系統層面阻止 dsh plugin --profile safemode add <包>:pnpm 寫這些文件會失敗,安裝直接報錯,插件進不去;DSH 啓動不受影響。共三級:
1、基礎只讀(推薦日常使用):Windows 用 attrib +R,POSIX 用 chmod 444:
attrib +R "$env:USERPROFILE\.dsh\profiles\safemode\package.json" `
"$env:USERPROFILE\.dsh\profiles\safemode\cordis.patch.yml" `
"$env:USERPROFILE\.dsh\profiles\safemode\pnpm-workspace.yaml"
chmod 444 ~/.dsh/profiles/safemode/package.json \
~/.dsh/profiles/safemode/cordis.patch.yml \
~/.dsh/profiles/safemode/pnpm-workspace.yaml
2、Windows ACL(icacls deny):可精確到“寫”與“刪”,但仍擋不住管理員,Administrators / SYSTEM 默認完全控制,可通過取得所有權繞開;
3、Linux immutable(chattr +i):最強的一檔,root 也動不了,但需要 sudo,且文件系統要支持(ext4/xfs 支持)。
加固的幾個注意點:
- 只鎖這三個受管文件,不要鎖整個目錄。Windows 下尤其不要用
attrib +R <目錄> /S遞歸加鎖——DSH 每次啓動都會重寫cordis.yml,目錄被鎖會導致 safemode 啓動失敗(實測 exit 1)。 - 先讓插件創建/還原 profile,內容與白名單模板一致後再鎖。鎖定後若出現漂移,守護還原會因只讀而失敗並記 warn——這正是鎖定的預期行爲:鎖住即不該有漂移。
chattr +i會連守護的自愈重建一起擋住,升級插件、修改白名單前都要先chattr -i。日常場景用基礎只讀就夠了。
適用場景與注意¶
適合的場景:需要一個可預期的乾淨 DSH 環境做排障或對照;機器上有自動化腳本或其他人會碰 DSH 配置,希望 safemode 不被意外(或故意)改動。
使用前需要清楚的幾件事:
1、端口衝突:safemode 也帶 webServer,默認 3080。與 web profile 同時跑會因 EADDRINUSE 啓動失敗,用 --port 錯開(如 --port 3081)。
2、會話與憑據不隔離:sessions、settings.yaml、.env 是 home 級共享,safemode 隔離的只有插件。
3、home patch 串層:~/.dsh/cordis.patch.yml 對每個 profile 都生效,別往裏面掛插件,守護邏輯只盯 safemode 自己的目錄。
4、cordis.yml 不要手改:DSH 每次啓動自動重寫它。safemode 的 patch 層會被本插件還原爲空,定製走 DSH_SAFEMODE_BUNDLES。
最後照例提醒:插件以當前 dsh 進程的權限運行,安裝前建議先讀一遍源碼(倉庫見文末鏈接)與許可證(MIT),確認符合你的安全要求再裝。
小結¶
dsh-safemode-profile 只做一件事:讓 dsh --profile safemode 永遠乾淨。啓動強制還原、運行期雙通道守護,配合可選的文件系統只讀加固,safemode 不會再悄悄“變髒”。
- 插件目錄頁:https://www.skillhub.cn/plugins/jinsiyu/dsh-safemode-profile
- GitHub 倉庫:https://github.com/jinsiyu/dsh-safemode-profile
其中目錄頁是社區維護的獨立站點,與 DeepSeek / 幻方無官方從屬關係,僅作檢索入口。