dsh-safemode-profile:讓 dsh --profile safemode 啓動即零第三方插件

前言

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 / 幻方無官方從屬關係,僅作檢索入口。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜