SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-22

dsh 外掛怎麼運作?安裝前如何檢查安全性

安裝 dsh 外掛會以代理程式權限執行他人程式碼,且沒有隔離。了解外掛可存取的 LLM、Shell、檔案與憑證,以及安裝前的檢查方法。

什麼是 dsh 外掛,它可以做什麼?

dsh 外掛是 DeepSeek Harness 載入自身程序的 Node 套件。安裝外掛會以代理程式的權限,在代理程式已能連線的機器上執行他人的程式碼。載入的外掛與 Harness 的其他部分之間沒有隔離。因此,安裝前應先確認該程式碼能存取哪些內容,以及如何將可存取範圍縮到最小。

dsh (DeepSeek Harness) 是 DeepSeek AI 的開放原始碼代理程式 Harness,建置於名為 Cordis 的外掛架構上。專案自己的 README 表示,所有功能都是外掛。模型介面卡是外掛。你用來輸入內容的 Web 介面也是外掛。從專案外部安裝的任何元件,都會進入相同的元件樹,並與隨專案提供的部分具有相同的信任層級。如果你尚未建立執行個體,請先參閱 在 VPS 上部署 DeepSeek Harness,再回來新增元件。

外掛可存取的擴充點列在儲存庫的 AGENTS.md 中。截至 2026 年 8 月,涵蓋以下項目:

  • LLM(大型語言模型):由你的 API key 支付費用的提供者
  • Shell:bash 功能,包含 local 和 pwsh 提供者
  • Filesystem:受政策控制的檔案存取
  • Web:搜尋與擷取提供者
  • Subprocess:程序樹提供者
  • Workflow:worker threads
  • Subagent:委派工作給其他代理程式
  • Settings and credentials:已儲存的設定與環境變數

外掛也會在 ctx.tools 上註冊工具,而文件明確說明,已註冊工具的 schema 會加入提示組裝流程。後半段容易被忽略。外掛不必在自身程式碼中執行異常操作,也能改變代理程式決定採取的行動,因為外掛提供的描述會成為模型讀取的文字。這與針對 coding agents 的提示注入屬於同類問題,但有一項差異:這些文字會在安裝外掛時加入,並持續存在,直到你移除外掛為止。

dsh 如何尋找並載入外掛程式?

dsh 沒有全域外掛程式目錄。執行中的 dsh 是在啟動時,由依序套用的多個層組成的外掛程式樹;保存這些選擇的單位是設定檔。$DSH_HOME 預設為 ~/.dsh,每個設定檔都位於 $DSH_HOME/profiles/<name>webheadless 設定檔會在首次使用時,根據隨附的範本自行建立。

設定檔目錄包含 2 個決定所有內容的檔案:

  • package.json,包含樹外外掛程式相依性,以及帶有依序排列 bundles 清單的 dsh.profile manifest
  • cordis.patch.yml,您自行建立、套用在這些 bundle 上的修補層
ls ~/.dsh
ls ~/.dsh/profiles/web

啟動時會依照以下順序套用各層,後套用的層優先:

  1. 空白根目錄
  2. 設定檔的 bundle,順序依 manifest 列出的內容
  3. 設定檔的 cordis.patch.yml
  4. $DSH_HOME/cordis.patch.yml
  5. 在命令列傳入的任何 --patch <path> overlay

以下 2 個旗標會列印組合結果,但不會啟動任何內容:

dsh --profile web --dump-default-config
dsh --profile web --dump-config

--dump-default-config 只會列印組合後的樹。--dump-config 會加入設定檔與 home 修補層,因此最接近如實列出下一次啟動將載入的內容。在信任接手的機器前,請先查看此清單。

請注意這些修補檔。這裡的設定不是單純的資料,因為該格式允許在外掛程式的 config 區塊中使用帶有 !!js 標籤的值。從論壇貼文複製的 cordis.patch.yml 片段就是程式碼,請按照處理同一來源 shell script 的方式處理它。

dsh plugin add 實際執行什麼?

dsh plugin --profile <name> <args> 會將其引數轉送給該設定檔目錄中的 pnpm,因此 PATH 中必須有 pnpm。這些動詞是 pnpm 的動詞:

dsh plugin --profile web add '<package-or-git-spec>'
dsh plugin --profile web remove '<package-name>'
dsh plugin --profile web why '<package-name>'
dsh plugin --profile web update

因此,安裝 dsh 外掛程式的安全性模型,就是安裝任何 npm 風格相依套件的安全性模型,另外再加上將結果載入 agent 的步驟。該套件會攜帶自己的相依性樹,而這棵樹中的每個套件最後都會在同一個程序中執行。npm 供應鏈攻擊如何觸及伺服器 中的所有內容都適用於此,無須修改。

pnpm 10 及更新版本預設不會執行相依套件的建置指令碼,而是透過 onlyBuiltDependenciespnpm approve-builds 逐一核准套件。請檢查目前使用的 pnpm 版本:

pnpm --version

這項預設值值得保留,但它也是生態系中最容易被過度解讀的安全功能。遭封鎖的建置指令碼會阻止程式碼在安裝期間執行,但無法處理外掛程式本身,因為外掛程式的作用就是由 harness 匯入,並在下次啟動時呼叫它。外掛程式不需要 postinstall hook。它本來就是受邀載入的。

安裝 dsh 外掛前應先閱讀的內容

下載已發布的 tarball 並閱讀內容。解開封存檔時不會執行任何程式。

npm pack '<package-name>@<version>'
tar -tzf '<package-name>-<version>.tgz'
tar -xzf '<package-name>-<version>.tgz'
less package/package.json

package.json 中的 4 個欄位能提供大部分必要資訊。閱讀 scripts,查看 preinstallinstallpostinstall 項目。對於不熟悉的名稱,或只與已知名稱相差 1 個字元的名稱,請閱讀 dependencies。若套件要求將任何內容加入 PATH,請閱讀 bin。若要找出入口檔案,請閱讀 mainexports,接著開啟該檔案並追蹤其內容。

接著閱讀實際會載入的程式碼。宣稱提供通知工具的外掛,沒有理由讀取 ~/.ssh、呼叫你從未聽過的主機,或啟動 shell。如果套件只提供內嵌或最小化的 JavaScript,且公開 repository 中沒有對應原始碼,答案就很明顯。優先選擇可閱讀原始碼的外掛,並優先選擇小型外掛。

你也可以在不安裝任何內容的情況下查詢 registry:

pnpm view '<package-name>' dependencies
pnpm view '<package-name>' versions

上週發布、只有 1 個版本、沒有 repository 欄位,而且名稱仿冒熱門套件的套件,是任何 registry 中最老套的手法。使用 checksum 驗證下載內容 是相鄰的必要習慣:在允許內容執行前,確實確認你下載了什麼。

固定版本,並保留 lockfile

浮動版本範圍表示 agent 程序中的程式碼,可能在任何一次安裝或更新時變更,而無須經過你的決定。請固定版本。

dsh plugin --profile web add --save-exact '<package-name>@<version>'

不同 pnpm 版本的旗標位置可能不同,因此請檢查結果,不要直接信任指令。接著開啟 profile 的 package.json,確認相依性顯示為不含 ^~ 前綴的單純版本。這個檔案決定實際安裝的內容。

接著保留 lockfile。它會固定整個轉移相依性樹,而不只是頂層名稱:

find ~/.dsh -maxdepth 3 -name 'pnpm-lock.yaml'

將它與 profile 的 package.json 一起複製到備份位置。這兩個檔案可在新主機上重建相同的相依性樹。只有在決定變更版本時才執行 dsh plugin --profile web update,不要把它當作例行整理工具,並在執行後檢查 lockfile 的差異。

如果外掛是從 git 而非 registry 安裝,請固定 commit,不要固定 branch。github:owner/repo#<full commit sha> 形式的規格會提供固定的相依性樹。branch 名稱則會在 pnpm 下次解析時,採用該 branch 當時包含的內容;這等於把決定權交給其他人。harness 本身也需要遵循相同原則,因為每個已發布的 dsh build 都是 release candidate,而未固定版本的安裝可能在任何一天解析到不同版本,這正是多數 dsh 安裝與版本錯誤的來源。

插件市集,以及「策展」的價值

dsh 具備市集,而且市集以插件形式安裝。這反映出其架構設計:

dsh plugin --profile web add dshmarket

重新啟動後,前往 Settings,再選擇 Plugin Market,即可看到市集。其 README 明確說明了限制。插件只能從策展登錄所列出的來源安裝,其他來源一律拒絕。建置指令碼預設會遭封鎖;若要啟用,必須逐一核准套件。終端機插件加入 Web 設定檔前,會先顯示警告。最重要的一句話是:列入清單不代表推薦,因為這些插件是第三方程式碼。

策展清單能提高最低安全標準,但不會替你閱讀程式碼,也無法預測插件維護者帳號易手後,下一個版本會執行什麼操作。請用對待同一位作者提供的 curl | bash 的方式,來看待一鍵安裝。README 中還有一句話值得重申:匯出的備份可能包含設定檔中的憑證,因此絕不要將備份附加到公開 issue 或貼文網站。如果你需要的是起始清單,而不是方法,值得安裝的 dsh 插件 是本文的配套文章。

以專用使用者執行 dsh,不要使用 root

審查可降低惡意內容進入的頻率。最小權限則決定惡意內容進入後能接觸哪些資源。在 VPS 上,設定這一層防護的成本很低。

為 harness 建立專用的 Unix 帳號與家目錄,並且永遠不要以 root 執行:

sudo adduser --disabled-password --gecos "" dshrun
sudo -iu dshrun

在該工作階段中啟動 harness,讓它以該帳號的家目錄作為寫入位置:

npx @deepseek-ai/dsh web

Web UI 預設在 http://127.0.0.1:3080 提供服務。請維持此設定。任何能連線到該埠的使用者,都能操作具有 shell 的 agent,因此公開 3080 等同於公開一個具備友善介面的無 root 權限遠端 shell。請改用 SSH tunnel,從筆記型電腦連線:

ssh -L 3080:127.0.0.1:3080 you@your-vps

接著確認沒有程序監聽公開位址:

ss -lnt | grep 3080

本機位址應顯示為 127.0.0.1:3080。如果顯示為 0.0.0.0:3080,防火牆就是陌生使用者與 agent 之間唯一的防線。在 VPS 上安全執行 Claude Code 的原則同樣適用於 dsh。為 agent 指定一個允許其任意修改的工作區目錄,並將所有無法重建的資料移出該主機。更好的做法是將該主機視為供 coding agent 使用的一次性 VM,因為重建 VPS 只需一小時,稽核 VPS 卻可能需要一週。

金鑰存放位置,以及檔案權限的實際限制

dsh 將 API 金鑰儲存在 $DSH_HOME/.credentials.yaml,將環境值儲存在 $DSH_HOME/.env,模型設定儲存在 $DSH_HOME/settings.yaml,工作階段歷程則位於 $DSH_HOME/storages。哪些金鑰應放在哪個檔案,以及各模式下實際有哪些內容會離開主機,是 設定 dsh 的 API 金鑰、模型與端點 所要說明的主題。建議在新增外掛程式前先釐清,因為你接入的每個金鑰,都會多一項外掛程式可以讀取的內容。請先鎖定以下兩個敏感檔案:

chmod 600 ~/.dsh/.credentials.yaml ~/.dsh/.env
ls -l ~/.dsh

模式 600 允許擁有者讀取和寫入,其他使用者則完全沒有權限。這在兩種表示法中都值得了解(數字與符號 chmod 模式)。但必須清楚了解它的作用。檔案模式可防止主機上的其他帳號存取這些檔案,但無法防止外掛程式存取,因為外掛程式會以檔案擁有者的身分執行,且位於讀取這些檔案的程序中。因此,讓密鑰不落入 AI 代理程式的存取範圍 就代表根本不要將密鑰放在該機器上。dsh 主機只應保存所需的那一組模型金鑰。雲端憑證與簽署金鑰應存放在其他位置。

讀取網頁的外掛為何會改變威脅模型

Web 接口會為外掛提供搜尋與擷取服務。外掛將頁面載入工作階段時,載入的是攻擊者可以撰寫的文字。模型提示不會區分指示與資料,因此擷取的頁面可能包含一行直接寫給代理程式的指示,而持有 shell 能力的 harness 只需順從一步,就可能執行該指示。

harness 中已經存在控制機制。dsh-base 是每個設定檔中的第一個 bundle,提供 sandbox 與核准政策。請使用它。能夠擷取不受信任頁面的工作階段,應要求所有寫入或執行操作都先取得核准,讓擷取到的指示無法自行轉化為動作。將代理程式動作置於核准機制之後說明應如何思考這條界線的位置。這種關係也會雙向成立,因為你自己的伺服器也是其他代理程式會擷取的頁面;這正是在你的伺服器上封鎖 AI 爬蟲所處理的情境。

如何檢查外掛程式變更了哪些內容?

先建立快照,再安裝外掛程式,接著建立安裝後快照,最後讀取差異。

dsh --profile web --dump-config > /tmp/dsh-before.txt
dsh plugin --profile web add '<package-name>@<version>'
dsh --profile web --dump-config > /tmp/dsh-after.txt
diff -u /tmp/dsh-before.txt /tmp/dsh-after.txt

差異會顯示安裝作業在組合後的樹狀結構中加入了哪些外掛程式項目。如果你為了單一小功能安裝的外掛程式加入了多個無法說明用途的項目,就應該先停止操作並閱讀原始碼,再啟動該外掛程式。dsh plugin --profile web why <package-name>則回答另一個問題:是哪個直接相依項目拉入指定的套件。

已安裝的套件會放在 $DSH_HOME/profiles/node_modules 下,因此你也可以查看磁碟上的樹狀結構:

ls ~/.dsh/profiles/node_modules

保留第二個設定檔,且不要在其中進行實驗。安裝作業使測試框架失效時,啟動 dsh --profile <clean-name> 即可在數秒內確認是否由該外掛程式造成。

如何移除 dsh 外掛程式?

dsh plugin --profile web remove '<package-name>'
dsh --profile web --dump-config > /tmp/dsh-after-removal.txt
diff -u /tmp/dsh-before.txt /tmp/dsh-after-removal.txt

移除相依套件不一定會移除設定。寫入設定檔的 cordis.patch.yml 內容仍會保留,因為該檔案由你管理,執行框架不會替你改寫。開啟該檔案,刪除任何指定已移除套件的區塊。

less ~/.dsh/profiles/web/cordis.patch.yml

接著處理任何解除安裝命令都無法修復的部分。如果你因為不再信任某個外掛程式而將其移除,那麼它原本能讀取的內容,可能早已被讀取。請在 provider console 中輪替 DeepSeek API key,並輪替當時存放在 $DSH_HOME 中的其他內容。接著確認該外掛程式執行所用的 unix account 能存取網路中哪些其他資源。

簡要重點

  • 安裝前先閱讀已發布的 tarball,從 scripts 和入口檔案開始
  • 固定確切版本;若使用 git 規格,則固定確切 commit,並保留 lockfile
  • 安裝到單一 profile,並保留一個乾淨的 profile,以便發生問題時啟動
  • 每次安裝前後都比較 --dump-config
  • 讓 harness 以獨立的 Unix 使用者、在 loopback 上執行,並透過 SSH 存取
  • 在該主機上只保留一組 API key,移除不再信任的 plugin 時立即輪替

這些都不是避免使用 plugin 的理由。plugin model 正是 dsh 實用的原因,而無法擴充的 harness 最終會被替換。重點是確認已安裝的內容、來源與版本,並將整套環境執行在可重新建置的位置。

FAQ

dsh 會將外掛彼此隔離嗎?

不會。外掛會透過 Cordis 載入 harness 程序,並可存取文件所述的能力介面,包括 shell、filesystem、web、subprocess、subagent 和 credentials。dsh-base 是每個 profile 中的第一個 bundle,負責提供 sandbox 與核准政策,以規範 agent 的工具可執行哪些操作;你的防護來自這項政策。外掛之間沒有個別的權限邊界,因此更準確的理解是:安裝外掛等同於信任其作者,以及其相依性樹中的每個套件。

不執行安裝腳本時,可以安裝 dsh 外掛嗎?

pnpm 10 及後續版本預設會封鎖相依套件的建置腳本,而 dsh plugin ... add 會轉交給 pnpm 處理。因此,使用目前版本的 pnpm 時,除非核准該套件,安裝程序不會執行套件腳本。使用 pnpm --version 確認版本。這不代表未讀取原始碼的外掛就是安全的。下一次啟動時,harness 會刻意載入外掛的程式碼,因此外掛自身的程式碼仍會執行;安裝時的限制無法阻止這件事。

dsh 外掛及其設定實際儲存在哪裡?

$DSH_HOME 預設為 ~/.dsh。Profiles 位於 $DSH_HOME/profiles/<name>。每個 profile 都包含一個 package.json,其中有外掛相依性;也包含按順序排列的 bundle manifest dsh.profile,以及 cordis.patch.yml patch layer。已安裝的套件會放在 $DSH_HOME/profiles/node_modules 下。金鑰位於 $DSH_HOME/.credentials.yaml,環境值位於 $DSH_HOME/.env,而 home 層級的 $DSH_HOME/cordis.patch.yml 會套用至每個 profile。執行 dsh --profile web --dump-config 可查看組合後的結果,而不啟動 harness。

從 dsh 外掛市場安裝是否安全?

該市場只允許從精選 registry 中的來源安裝,並會封鎖建置腳本,除非你逐一核准套件。與從聊天視窗直接貼上套件名稱相比,這確實有所改善。不過,市場自己的 README 仍明確指出,列出外掛不代表背書,因為這些外掛是其他人提供的第三方程式碼。請閱讀原始碼並鎖定版本。請在你能承受遺失的使用者帳戶上執行 harness,理想情況下也應在能承受遺失的機器上執行。