Plugin dsh có thể làm gì và cách kiểm tra an toàn
Cài plugin dsh là chạy code của người khác với quyền của agent, không có sandbox. Xem plugin truy cập gì và cách kiểm tra trước khi cài.
Plugin dsh là gì và có thể làm được gì?
Plugin dsh là các package Node được DeepSeek Harness load vào process của chính nó. Khi cài một plugin, bạn chạy code của người khác với các quyền của agent, trên máy mà agent đã có thể truy cập. Không có lớp ngăn cách nào giữa plugin đã load và phần còn lại của harness. Vì vậy, trước khi cài một plugin, bạn cần hỏi code đó có thể truy cập những gì và bạn giới hạn phạm vi đó như thế nào.
dsh (DeepSeek Harness) là agent harness mã nguồn mở của DeepSeek AI, được xây dựng trên một plugin framework có tên Cordis. README của dự án nêu rõ rằng mọi thành phần đều là plugin. Model adapter là một plugin. Web interface mà bạn nhập dữ liệu vào cũng là một plugin. Mọi thứ bạn cài từ bên ngoài dự án đều nằm trong cùng một cây và có cùng mức độ tin cậy với các thành phần đi kèm dự án. Nếu bạn chưa dựng dsh, hãy bắt đầu với DeepSeek Harness trên một VPS, rồi quay lại trước khi thêm bất kỳ thứ gì vào đó.
Các extension point mà plugin có thể truy cập được liệt kê trong AGENTS.md của repository. Tính đến August 2026, chúng bao gồm:
- LLM (large language model): provider mà API key của bạn thanh toán
- Shell: khả năng chạy bash, với các provider local và pwsh
- Filesystem: quyền truy cập file được kiểm soát bằng policy
- Web: các provider search và fetch
- Subprocess: provider quản lý cây process
- Workflow: các worker thread
- Subagent: ủy quyền công việc cho các agent khác
- Settings and credentials: cấu hình đã lưu và các biến môi trường của bạn
Plugin cũng đăng ký các tool trên ctx.tools, và tài liệu nêu rõ schema của tool đã đăng ký sẽ được đưa vào quá trình dựng prompt. Đây là phần thường bị bỏ qua. Plugin có thể thay đổi quyết định của agent mà không cần code của nó làm điều gì bất thường, vì phần mô tả mà plugin thêm vào trở thành văn bản để model đọc. Đây cũng là dạng vấn đề giống với prompt injection nhằm vào coding agent, nhưng có một điểm khác: văn bản này xuất hiện khi bạn cài plugin và vẫn tồn tại cho đến khi bạn gỡ plugin.
dsh tìm và nạp plugin như thế nào?
Không có thư mục plugin global. Một dsh đang chạy là một cây plugin được ghép khi boot từ các layer theo thứ tự. Đối tượng lưu các lựa chọn của bạn là một profile. $DSH_HOME mặc định là ~/.dsh, và mỗi profile nằm trong $DSH_HOME/profiles/<name>. Các profile web và headless được tự tạo khi sử dụng lần đầu từ các template đã được cung cấp.
Thư mục profile chứa 2 file quyết định toàn bộ cấu hình:
package.json, chứa các dependency của plugin ngoài cây mã nguồn, cùng với một manifestdsh.profilechứa danh sáchbundlestheo thứ tựcordis.patch.yml, layer patch riêng của bạn áp dụng trên các bundle đó
ls ~/.dsh
ls ~/.dsh/profiles/webKhi boot, các layer được áp dụng theo thứ tự sau. Layer đứng sau sẽ ghi đè layer đứng trước:
- một root rỗng
- các bundle của profile, theo thứ tự trong manifest
cordis.patch.ymlcủa profile$DSH_HOME/cordis.patch.yml- mọi overlay
--patch <path>được truyền trên command line
Có 2 flag in ra kết quả ghép này mà không khởi động bất cứ thứ gì:
dsh --profile web --dump-default-config
dsh --profile web --dump-config--dump-default-config chỉ in riêng cây đã ghép. --dump-config thêm các layer patch của profile và home, nên đây là cách gần nhất để xem đầy đủ những gì lần boot tiếp theo sẽ nạp. Hãy đọc kết quả trước khi tin tưởng một máy được bàn giao cho bạn.
Có một cảnh báo về các file patch đó. Config ở đây không chỉ là dữ liệu thụ động, vì format cho phép các giá trị được gắn tag !!js bên trong block config của plugin. Một đoạn cordis.patch.yml được sao chép từ bài đăng trên forum là code. Hãy xử lý nó như một shell script từ cùng nguồn.
dsh plugin add thực sự chạy gì?
dsh plugin --profile <name> <args> chuyển tiếp các đối số của nó cho pnpm trong thư mục của profile đó, vì vậy pnpm phải có trong PATH. Các verb là verb của 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 updateMô hình bảo mật khi cài đặt một plugin dsh là mô hình bảo mật của việc cài đặt bất kỳ dependency kiểu npm nào, cộng thêm một bước: kết quả được load vào agent của bạn. Package mang theo cây dependency riêng, và mọi package trong cây đó đều chạy trong cùng một process. Mọi nội dung trong cách các cuộc tấn công chuỗi cung ứng npm tiếp cận server đều áp dụng ở đây mà không cần thay đổi.
pnpm 10 trở lên không chạy build script của dependency theo mặc định. Việc phê duyệt được thực hiện theo từng package thông qua onlyBuiltDependencies hoặc pnpm approve-builds. Kiểm tra phiên bản pnpm đang dùng:
pnpm --versionĐây là một mặc định đáng duy trì, nhưng cũng là tính năng an toàn thường bị hiểu quá mức trong hệ sinh thái này. Build script bị chặn sẽ ngăn code chạy trong lúc cài đặt. Chúng không làm gì với bản thân plugin, vì mục đích của plugin là để harness import nó và gọi nó trong lần boot tiếp theo. Plugin không cần hook postinstall. Nó đã được bạn cho phép chạy.
Đọc gì trước khi cài plugin dsh
Hãy tải tarball đã được công bố và đọc nội dung của nó. Không có gì được thực thi khi bạn giải nén archive.
npm pack '<package-name>@<version>'
tar -tzf '<package-name>-<version>.tgz'
tar -xzf '<package-name>-<version>.tgz'
less package/package.jsonBốn trường trong package.json cung cấp gần như mọi thông tin bạn cần. Đọc scripts để xem các mục preinstall, install và postinstall. Đọc dependencies để kiểm tra những tên bạn không nhận ra hoặc những tên chỉ khác một ký tự so với tên quen thuộc. Đọc bin để xem mọi thứ package muốn có trong PATH của bạn. Đọc main hoặc exports để tìm file entry, sau đó mở file đó và lần theo nội dung.
Tiếp theo, hãy đọc code thực sự được load. Một plugin quảng cáo công cụ thông báo không có lý do gì để đọc ~/.ssh, gọi đến một host bạn chưa từng biết hoặc spawn một shell. Nếu package chỉ ship JavaScript đã bundled hoặc minified mà không có source tương ứng trong một repository công khai, thì đó chính là câu trả lời. Ưu tiên các plugin có source mà bạn có thể đọc, và ưu tiên plugin nhỏ.
Bạn cũng có thể kiểm tra registry mà không cần cài đặt gì:
pnpm view '<package-name>' dependencies
pnpm view '<package-name>' versionsMột package được publish vào tuần trước, chỉ có một version, không có trường repository và có tên gần giống một package phổ biến là thủ thuật cũ nhất trong mọi registry. Xác minh file tải xuống bằng checksum là thói quen liên quan: hãy biết chính xác bạn đã tải gì trước khi cho phép nó chạy.
Ghim version và giữ lockfile
Một dải version không cố định có nghĩa là code bên trong process của agent có thể thay đổi sau mỗi lần install hoặc update mà bạn không cần quyết định gì. Hãy ghim version.
dsh plugin --profile web add --save-exact '<package-name>@<version>'Vị trí flag thay đổi giữa các version của pnpm, vì vậy hãy kiểm tra kết quả thay vì tin hoàn toàn vào command. Sau đó mở package.json của profile và xác nhận dependency hiển thị dưới dạng version thuần, không có ^ hoặc ~ ở trước. File đó quyết định nội dung được install.
Tiếp theo, hãy giữ lockfile. Lockfile ghim toàn bộ cây dependency transitive, thay vì chỉ ghim tên dependency cấp cao nhất:
find ~/.dsh -maxdepth 3 -name 'pnpm-lock.yaml'Sao chép file này vào nơi bạn backup, cùng với package.json của profile. Hai file đó có thể dựng lại cùng một cây dependency trên máy mới. Chạy dsh plugin --profile web update khi bạn đã quyết định đổi version, không chạy như một thao tác dọn dẹp định kỳ. Sau đó đọc diff của lockfile.
Với plugin được install từ git thay vì registry, hãy ghim commit thay vì branch. Spec có dạng github:owner/repo#<full commit sha> sẽ cho bạn một cây dependency cố định. Tên branch sẽ cho bạn nội dung mà branch đó chứa vào lần pnpm resolve tiếp theo. Khi đó, bạn đã giao quyết định này cho người khác. Harness cũng cần tuân thủ nguyên tắc tương tự, vì mỗi bản dsh được publish đều là một release candidate và một lần install không ghim version có thể resolve thành bản khác vào bất kỳ ngày nào. Đây là nguyên nhân của phần lớn lỗi install và version của dsh.
Thị trường plugin và giá trị thực của việc “curated”
dsh có marketplace và được cài dưới dạng plugin. Điều này cho thấy một phần về kiến trúc của nó:
dsh plugin --profile web add dshmarketSau khi restart, mục này xuất hiện trong Settings, rồi đến Plugin Market. README của nó nêu rõ các giới hạn. Việc cài đặt chỉ được phép từ những source có trong curated registry; mọi source khác đều bị từ chối. Build script bị chặn mặc định. Muốn bật một build script, bạn phải phê duyệt riêng từng package. Plugin terminal sẽ được đánh dấu trước khi đưa vào web profile. Câu quan trọng nhất là việc được liệt kê không đồng nghĩa với được chứng nhận, vì các plugin là code của bên thứ ba.
Danh sách curated giúp nâng mức an toàn tối thiểu. Nhưng nó không đọc code thay bạn và cũng không thể cho biết phiên bản tiếp theo của plugin sẽ làm gì sau khi tài khoản maintainer được chuyển cho người khác. Hãy xem việc cài đặt bằng một cú nhấp giống như khi bạn xử lý curl | bash từ cùng tác giả. Một dòng khác trong README cũng đáng được nhắc lại: backup đã export có thể chứa credential từ profile config của bạn. Vì vậy, không bao giờ đính kèm backup đó vào issue công khai hoặc paste site. Nếu bạn cần một danh sách khởi đầu thay vì phương pháp, các plugin dsh đáng cài đặt là bài viết đi kèm với bài này.
Chạy dsh bằng user riêng, không chạy bằng root
Kiểm tra giúp giảm tần suất hệ thống bị xâm nhập. Least privilege quyết định kẻ xâm nhập có thể tiếp cận đến đâu. Trên VPS, thiết lập phần này không tốn nhiều công sức.
Tạo một unix account riêng cho harness, có home riêng, và không bao giờ chạy harness bằng root:
sudo adduser --disabled-password --gecos "" dshrun
sudo -iu dshrunTrong session đó, khởi động harness để nó tạo home dưới account này:
npx @deepseek-ai/dsh webWeb UI mặc định lắng nghe trên http://127.0.0.1:3080. Hãy giữ nguyên cấu hình đó. Bất kỳ ai truy cập được cổng này đều có thể điều khiển một agent có shell, vì vậy publish cổng 3080 tương đương publish một remote shell không có quyền root, nhưng có giao diện dễ dùng. Hãy truy cập từ laptop qua SSH tunnel:
ssh -L 3080:127.0.0.1:3080 you@your-vpsSau đó xác nhận không có tiến trình nào đang lắng nghe trên địa chỉ public:
ss -lnt | grep 3080Địa chỉ local phải hiển thị là 127.0.0.1:3080. Nếu hiển thị 0.0.0.0:3080, firewall là lớp bảo vệ duy nhất giữa người lạ và agent của bạn. Lý do đằng sau việc chạy Claude Code an toàn trên VPS cũng áp dụng nguyên vẹn cho dsh. Chỉ cấp cho agent một workspace directory mà nó được phép phá hỏng, và giữ mọi thứ không thể rebuild bên ngoài máy đó. Tốt hơn nữa, hãy coi máy này là một VM có thể loại bỏ cho coding agent, vì rebuild một VPS mất một giờ, còn audit một VPS mất cả tuần.
Vị trí lưu key và lý do quyền file chỉ bảo vệ được một phần
dsh lưu API key trong $DSH_HOME/.credentials.yaml và các giá trị môi trường trong $DSH_HOME/.env, còn cấu hình model nằm trong $DSH_HOME/settings.yaml và lịch sử session nằm dưới $DSH_HOME/storages. Key nào thuộc file nào, và ở mỗi mode thực tế dữ liệu nào rời khỏi máy, được giải thích trong cấu hình API key, model và endpoint cho dsh. Bạn nên xác định rõ việc này trước khi thêm plugin, vì mỗi key được cấu hình là thêm một dữ liệu mà plugin có thể đọc. Hãy khóa chặt 2 file nhạy cảm:
chmod 600 ~/.dsh/.credentials.yaml ~/.dsh/.env
ls -l ~/.dshMode 600 cho owner quyền đọc và ghi, đồng thời không cho những người dùng khác quyền nào. Điều này hữu ích khi làm việc với cả 2 cách ghi quyền (mode chmod dạng số và dạng ký hiệu). Nhưng cần hiểu đúng giới hạn của nó. File mode bảo vệ các file đó khỏi những account khác trên máy. Chúng không bảo vệ được trước plugin, vì plugin chạy với user sở hữu các file đó, bên trong process đọc chúng. Vì vậy, đưa secret ra khỏi phạm vi truy cập của AI agent có nghĩa là không lưu chúng trên máy ngay từ đầu. Máy chạy dsh chỉ nên giữ key của model mà nó cần. Cloud credential và signing key của bạn nên được lưu ở nơi khác.
Vì sao plugin đọc web làm thay đổi mô hình mối đe dọa
Web seam cung cấp cho plugin các provider để tìm kiếm và fetch dữ liệu. Plugin đưa một trang vào session của bạn đang đưa vào văn bản mà attacker có thể kiểm soát. Prompt của model không tách biệt instruction với data, nên trang được fetch có thể chứa một dòng nhắm đến agent của bạn. Harness có shell capability khi đó chỉ còn cách một bước tuân lệnh là chạy dòng đó.
Cơ chế kiểm soát đã có sẵn trong harness. dsh-base, bundle đầu tiên trong mọi profile, cung cấp sandbox và approval policy. Hãy sử dụng nó. Một session có thể fetch các trang không đáng tin cậy nên yêu cầu approval đối với mọi thao tác ghi hoặc thực thi, để instruction được fetch không thể tự biến thành action. Đặt action của agent sau bước approval giải thích cách xác định ranh giới này. Mối quan hệ cũng có chiều ngược lại: server của bạn là một trang mà agent của người khác sẽ fetch. Đây là trường hợp cần chặn AI crawler trên server của bạn.
Làm thế nào để kiểm tra plugin đã thay đổi gì?
Chụp snapshot trước khi cài, cài đặt, chụp snapshot sau đó, rồi đọc phần khác biệt.
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.txtDiff cho biết những entry nào của plugin đã được thêm vào cây đã compose. Nếu một plugin được cài cho một tính năng nhỏ nhưng lại thêm nhiều entry mà bạn không thể giải thích, hãy dừng lại và đọc source trước khi boot plugin đó. dsh plugin --profile web why <package-name> trả lời câu hỏi còn lại: dependency trực tiếp nào của bạn đã kéo một package cụ thể vào.
Các package đã cài nằm dưới $DSH_HOME/profiles/node_modules, vì vậy bạn cũng có thể xem cây trên disk:
ls ~/.dsh/profiles/node_modulesHãy giữ một profile thứ hai mà bạn không bao giờ dùng để thử nghiệm. Khi một lần cài đặt làm harness bị lỗi, boot dsh --profile <clean-name> sẽ cho bạn biết trong vài giây plugin có phải nguyên nhân hay không.
Làm thế nào để gỡ một plugin 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.txtGỡ dependency không phải lúc nào cũng xóa cấu hình. Các entry được ghi vào cordis.patch.yml của profile vẫn còn nguyên, vì file đó thuộc về bạn và harness sẽ không tự viết lại. Mở file này và xóa mọi block có tên package bạn đã gỡ.
less ~/.dsh/profiles/web/cordis.patch.ymlSau đó xử lý phần mà không lệnh uninstall nào có thể khắc phục. Nếu bạn gỡ plugin vì không còn tin cậy nó, thì bất cứ dữ liệu nào plugin có thể đọc, nó đã đọc rồi. Rotate DeepSeek API key trong provider console, đồng thời rotate mọi thứ khác từng nằm trong $DSH_HOME. Sau đó xác định unix account mà plugin đã chạy dưới quyền account đó có thể truy cập những gì trên phần còn lại của network.
Tóm tắt ngắn
- Đọc tarball đã phát hành trước khi cài đặt, bắt đầu từ
scriptsvà file entry - Pin đúng version, hoặc đúng commit đối với git spec, và giữ lại lockfile
- Cài đặt vào một profile, đồng thời giữ một profile sạch để có thể khởi động khi xảy ra sự cố
- Diff
--dump-configtrước và sau mỗi lần cài đặt - Chạy harness bằng một unix user riêng, trên loopback và truy cập qua SSH
- Chỉ giữ một API key trên máy, rồi rotate key vào ngày bạn gỡ một plugin không còn tin cậy
Không điều nào trong số này có nghĩa là nên tránh plugin. Mô hình plugin là lý do dsh hữu ích, còn một harness không thể mở rộng là một harness bạn sẽ phải thay thế. Đây là lý do để biết mình đã cài gì, từ ai, ở version nào, và chạy toàn bộ hệ thống ở nơi bạn có thể rebuild.
FAQ
dsh có sandbox các plugin với nhau không?
Không. Cordis tải plugin vào process của harness, và plugin có thể truy cập các capability seam được tài liệu hóa, gồm shell, filesystem, web, subprocess, subagent và credentials. dsh-base, bundle đầu tiên trong mọi profile, cung cấp sandbox và approval policy kiểm soát những gì các tool của agent được phép làm. Đây là cơ chế bảo vệ của bạn. Không có permission boundary riêng cho từng plugin. Vì vậy, mô hình an toàn đúng là: khi cài một plugin, bạn mở rộng mức độ tin cậy cho tác giả plugin và mọi package trong dependency tree của plugin đó.
Tôi có thể cài plugin dsh mà không chạy install script của plugin không?
pnpm 10 trở lên mặc định chặn dependency build script. dsh plugin ... add chuyển tiếp đến pnpm, nên với pnpm hiện tại, quá trình cài đặt không chạy package script trừ khi bạn approve package đó. Kiểm tra version bằng pnpm --version. Điều này không làm cho plugin chưa được đọc mã nguồn trở nên an toàn. Code riêng của plugin sẽ chạy ở lần boot tiếp theo vì harness chủ động load plugin. Không có restriction trong lúc cài đặt nào ngăn được việc này.
Plugin dsh và config của chúng thực sự nằm ở đâu?
$DSH_HOME mặc định là ~/.dsh. Profile nằm trong $DSH_HOME/profiles/<name>. Mỗi profile chứa một package.json với các plugin dependency của profile, cùng manifest dsh.profile của các bundle theo đúng thứ tự và một patch layer cordis.patch.yml. Package đã cài nằm dưới $DSH_HOME/profiles/node_modules. Key nằm trong $DSH_HOME/.credentials.yaml, environment value nằm trong $DSH_HOME/.env, còn $DSH_HOME/cordis.patch.yml ở cấp home sẽ được áp dụng cho mọi profile. Chạy dsh --profile web --dump-config để xem kết quả đã compose mà không cần boot.
Cài đặt từ market plugin của dsh có an toàn không?
Market chỉ cho cài đặt từ các source trên registry đã được tuyển chọn và chặn build script trừ khi bạn approve từng package. Đây là cải thiện thực tế so với việc dán tên package từ một cửa sổ chat. Tuy nhiên, README của chính market vẫn nêu rõ rằng việc được liệt kê không đồng nghĩa với endorsement, vì plugin là code của bên thứ ba do người khác viết. Hãy đọc source và pin version. Chạy harness bằng user account, và tốt nhất là trên một máy, mà bạn có thể chấp nhận mất.