按 kubeconfig context 管控 kubectl 调用的策略插件:本地集群外硬拒绝不可逆操作,其余写操作请求人工确认。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-kubectl-guard
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:gengwg/dsh-kubectl-guard
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
该插件的 README 只有英文版本。
A DeepSeek Harness policy plugin that gates kubectl by kubeconfig context.
Irreversible verbs against a non-local cluster are denied outright. Recoverable writes ask first. Reads and local clusters are untouched.
It registers no tools of its own — it inspects the command argument of shell tool calls, so it covers whatever the agent runs.
Install
Requires pnpm, which dsh plugin shells out to.
From npm:
dsh plugin --profile web add dsh-kubectl-guard
From source, if you want to hack on it:
git clone https://github.com/gengwg/dsh-kubectl-guard
cd dsh-kubectl-guard
dsh plugin --profile web add "$PWD"
Either way, activation is automatic: the package declares dsh.bundle, so
dsh plugin add joins it to the profile's bundle stack. Restart dsh to load it.
Upgrading from 0.1.x, which installed as a plain dependency: delete the manual
insert entry from ~/.dsh/profiles/<profile>/cordis.patch.yml. Bundle and user
patch layers both apply, so leaving it in loads the guard twice.
Examples
Nothing to invoke. Ask the agent to do its normal work; the guard sits in the tool pipeline and inspects the shell command before it runs.
Blocked, with the cluster name replaced by a per-session pseudonym:
> delete the stuck nginx pod
Error: kubectl-guard: 'delete' is irreversible and ctx#4be1f92a is not a local
cluster. Denied.
Asked, so you approve it in the UI before it runs:
> roll out the new deployment
kubectl-guard: 'apply' writes to ctx#4be1f92a, which is not a local cluster.
[approve] [deny]
Untouched, because reads are not gated:
> what pods are failing in kube-system?
kubectl get pods -n kube-system --field-selector=status.phase!=Running
NAME READY STATUS RESTARTS
api-7d9f8c 0/1 CrashLoopBackOff 14
Untouched, because the context is local:
> wipe the test namespace on my kind cluster
kubectl --context kind-dev delete ns test
namespace "test" deleted
Dry runs are reads, so they pass and give the agent a way to show you a change before asking for it:
kubectl apply --dry-run=server -f deploy.yaml # allowed
kubectl apply -f deploy.yaml # asks
Turn the guard off for one session without editing config:
dsh web --patch <(echo '- id: kubectl-guard
disabled: true')
Behavior
| Command | Non-local context | Local context |
|---|---|---|
get, describe, logs, top |
allow | allow |
auth can-i |
allow | allow |
auth reconcile |
ask | allow |
config use-context, other mutating config subcommands |
ask | ask |
apply, patch, scale, exec |
ask | allow |
delete, drain, evict |
deny | allow |
scale --replicas=0 |
deny | allow |
apply --prune |
deny | allow |
replace --force |
deny | allow |
apply --dry-run=server |
allow | allow |
A context is local only if it matches localContexts. Everything else, including a kubeconfig that cannot be read, is treated as production.
The context is resolved the way the shell would resolve it: an explicit
--context wins, then --kubeconfig, then a KUBECONFIG= assignment written
inline on the same command line, then the ambient environment. That last case
matters -- without it, KUBECONFIG=/path/to/prod kubectl delete ... would be
judged against whatever your shell happened to point at.
Config
config:
localContexts: [minikube, 'kind-*', docker-desktop]
binaries: [kubectl, k]
guardedTools: [bash, pwsh]
showContextNames: false
showContextNames is off by default: blocked-command messages go to the model, and therefore to the LLM provider. With it off the model sees a stable per-session pseudonym like ctx#4be1f92a instead of your cluster's name.
Failing closed
A gate that can be talked around is worse than none. Anything unparseable — sh -c, command substitution, an unterminated quote — is treated as a mutation: denied if the text contains an irreversible verb, asked otherwise. An unknown verb asks rather than allows.
What this is not
This gates a cooperative agent, not an adversary. It reads the command string
the agent asked to run, so anything that hides the binary name from that string
defeats it by construction -- $KUBECTL delete ... with the name only in the
environment, a shell alias resolved at runtime, a base64 round-trip.
Indirection that still contains the literal name is caught: K=kubectl; $K delete pod foo is denied, because any $ expansion alongside a mention of a
guarded binary makes the command opaque, and opaque plus an irreversible verb
is a denial. But treat the guard as a seatbelt against a confused agent, not a
sandbox against a hostile one. If you need the stronger property, take the
credential away rather than filtering the command.
Limitations
- Only
kubectl. helm, argocd and flux are not covered; the verb table is data, so adding them is an edit tosrc/verbs.js. - Pass-through wrappers (
sudo,time,nice, ...) are seen through, but only until a bare-token wrapper argument:timeout 30 kubectl delete ...is not gated, because30ends the wrapper chain. current-contextis read with a line-anchored regex, not a YAML parser. Unreadable or unmatched means production, so the failure direction is safe.- The pseudonym salt is per-process: ids are stable within a session, not across restarts.
- Guards are synchronous, so the deny path does no I/O beyond a cached
readFileSync.
Test
npm test
MIT.
链接
同类插件
toby-bridges/api-relay-audit★ 884
从 DeepSeek Harness 对 AI API 中转站和 LLM 代理运行本地安全审计,生成 Markdown 报告,覆盖提示词注入、模型替换信号、工具调用改写、错误泄漏、流完整性和按 profile 启用的 Web3 风险。
SeaOf0/dsh-redteam-model★ 716
面向授权安全研究的 DSH 合集:九个工作模式(redteam 总控、渗透测试、代码审计、二进制分析、攻防评估、免杀对抗、应急溯源、云安全攻防、CTF 解题)与十五个运行时插件,设置页管理台支持一键部署、安装、更新与卸载。
howmp/dsh-pentest★ 609
面向 DeepSeek Harness 的授权渗透模式:以探索链路记录目标、线索、资产与漏洞,并在 Web 中可视化展示。
PerryLink/dsh-auto-review★ 233
审批链上的第二模型自动审查:只读审查子代理返回带理由的 allow/deny 结构化裁决,默认 fail-closed。
ADWMC/helm-d#helmd★ 225
单包逆向与渗透测试安全分析插件:首轮工具收敛、领域路由与 33 个工具,覆盖 APK、Web、原生二进制、协议、恶意样本与 LLM 场景的逆向分析、加壳脱壳与 License 破解绕过;内置 H-CoT 评估引擎(语义路由、/hcot 命令)、账本驱动的 Web 工作台与工具货架、磁盘案件工作区(证据链自动存证、E 编号结论校验、上下文压缩后恢复)、GitHub 工具检索与 361 篇按需参考文档。
NanmiCoder/dsh-auto-mode★ 164
在 Workspace Write 与 Full access 之间增加 Auto 权限档:日常操作留在官方 workspace-write 沙箱内,由当前会话模型复核升权与破坏性调用,精确的越界访问按次放行一次,意图不明时询问,命中关键路径则拒绝。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。