前面的文章已经完成了 Claude Code Marketplace 的主要运行链分析:
text
Marketplace
↓
Plugin 安装与落盘
↓
Harness 扫描和能力注册
↓
作用域合并与冲突处理
经过这些阶段,一个第三方 Plugin 已经可以向 Claude Code 注入多种能力:
text
Skills
Commands
Agents
Hooks
MCP Servers
LSP Servers
Scripts
但能力能够被加载,并不意味着能力应该被无条件信任。
一个 Plugin 可能只是提供代码规范和文档,也可能携带:
text
可执行 Shell 脚本
自动触发的 Hook
远程 MCP Server
本地 MCP 进程
具有工具权限的 Skill
拥有独立执行循环的 Agent
因此,当 Marketplace 从一个简单的能力目录发展成第三方生态后,真正重要的问题变成了:
Claude Code 如何保证一个被发现、安装和加载的 Plugin,不会突破用户和企业预期的安全边界?
这不是单一的"权限弹窗"问题,而是一条完整的供应链问题:
text
Plugin 从哪里来
↓
谁发布了它
↓
安装时用户看到了什么
↓
项目能否替用户自动启用
↓
Plugin 请求了哪些能力
↓
运行时能访问哪些文件、网络和工具
↓
更新后能力是否发生变化
↓
企业如何统一限制和审计
本文重点分析:
text
Marketplace 来源如何限制
Plugin 安装前如何建立信任
Project Plugin 为什么需要 Workspace Trust
Skill 如何申请工具权限
Hook 和 MCP 为什么属于高风险组件
Plugin 更新时如何识别权限变化
企业如何建立 Marketplace Allowlist
Plugin、Agent、Tool 和 Sandbox 如何形成完整安全边界
一、Claude Code 的安全问题首先是供应链问题
很多人提到 Agent 安全时,首先想到的是:
text
是否允许执行 Bash
是否允许修改文件
是否启用 Sandbox
这些当然重要,但对于 Marketplace 来说,风险在 Agent 真正执行之前就已经开始了。
完整的风险路径是:
text
未知 Marketplace
↓
引入未知 Plugin
↓
Plugin 携带未知 Skill / Hook / MCP
↓
Harness 加载这些能力
↓
模型或事件系统调用能力
↓
访问文件、网络、环境变量或外部系统
因此,Marketplace 安全不能只在最后一层拦截命令。
它至少包含四个边界:
text
第一层:Source Boundary
→ 允许从哪里获取 Marketplace
第二层:Install Boundary
→ 用户是否同意安装和信任 Plugin
第三层:Capability Boundary
→ Plugin 可以声明哪些能力
第四层:Runtime Boundary
→ 能力运行时究竟可以做什么
如果前三层缺失,只依赖最后的权限确认,会导致用户不断面对零散的运行时弹窗,却无法判断 Plugin 整体是否值得信任。
二、Marketplace 来源如何被限制
Claude Code 可以从多种来源添加 Marketplace:
text
GitHub Repository
普通 Git URL
远程 marketplace.json
本地目录
本地 JSON 文件
项目 settings.json
企业预置 Seed
这为个人开发和企业内部生态提供了灵活性,但也意味着:
Marketplace Source 本身就是第一道供应链入口。
如果用户可以任意添加 Source,那么任何 Git 仓库、本地目录或远程 JSON,都可能成为 Plugin 的分发渠道。
1. extraKnownMarketplaces:推荐来源,不是安全边界
项目或用户配置可以通过:
json
{
"extraKnownMarketplaces": {
"company-tools": {
"source": {
"source": "github",
"repo": "company/claude-plugins"
}
}
}
}
向用户推荐 Marketplace。
当仓库中包含该配置时,成员在信任项目目录后,会收到安装 Marketplace 和对应 Plugin 的提示;用户仍然可以跳过不需要的 Marketplace 或 Plugin。官方将这种机制定位为团队便利能力,并明确要求用户信任和显式同意。
因此:
text
extraKnownMarketplaces
→ 告诉团队应该去哪里找
但不等于:
→ 强制只允许这些来源
它解决的是分发便利性,不是来源封锁。
2. strictKnownMarketplaces:真正的来源 Allowlist
企业需要严格限制 Marketplace 来源时,可以在 Managed Settings 中配置:
text
strictKnownMarketplaces
它具有三种基本状态:
text
未配置
→ 用户可以添加任意 Marketplace
空数组 []
→ 禁止添加所有 Marketplace
→ 包括官方 Anthropic Marketplace
来源列表
→ 只允许精确匹配的来源
例如,只允许企业官方仓库:
json
{
"strictKnownMarketplaces": [
{
"source": "github",
"repo": "acme-corp/approved-plugins"
}
]
}
也可以固定具体 Ref:
json
{
"strictKnownMarketplaces": [
{
"source": "github",
"repo": "acme-corp/security-tools",
"ref": "v2.0"
}
]
}
还可以通过 hostPattern 限制到企业 Git Server,或者通过 pathPattern 只允许特定本地目录。Claude Code 会在 Marketplace 添加、Plugin 安装、更新、刷新和自动更新之前执行校验,而且 Managed Settings 不能被用户或项目覆盖。
这说明安全检查发生在:
text
网络访问或文件系统读取之前
而不是下载完之后再判断。
3. 为什么需要精确匹配
Marketplace Source 不只是一个域名,还可能包含:
text
Repository
Ref
Path
URL
协议形式
例如:
text
github.com/company/plugins
github.com/company/plugins@v2
github.com/company/plugins/path-a
github.com/company/plugins/path-b
它们可能来自同一仓库,但代表不同的供应链范围。
Claude Code 对大部分 Source 类型采用精确匹配,包括 GitHub 的 repo、ref、path 和远程 JSON 的完整 URL。URL 尾部斜杠、.git 后缀以及 SSH/HTTPS 形式也可能被视为不同来源。
这是因为:
text
信任一个仓库
≠
信任仓库中的所有 Branch、Tag 和子目录
例如:
text
main
→ 经过企业审查
experimental
→ 开发者测试分支
plugins/approved
→ 正式插件
plugins/lab
→ 未审核实验
来源治理需要精确到真正被批准的发布通道。
4. 禁止旁路安装
即使限制了 Marketplace,用户仍可能通过单次 CLI 参数 Sideload:
text
直接加载 Plugin 目录
直接加载 Agent
临时添加 MCP Server
企业如果要建立严格边界,还需要配合:
text
disableSideloadFlags
限制绕过 Marketplace 的单次加载方式。官方建议将它与 strictKnownMarketplaces 配合使用。
因此完整的企业来源控制不是:
text
只设置 Marketplace Allowlist
而是:
text
Marketplace Allowlist
+
禁止旁路加载
+
网络代理和仓库访问策略
三、Plugin 安装前如何建立信任
Marketplace 被允许,并不等于其中所有 Plugin 都已经可信。
需要区分:
text
信任 Marketplace Source
→ 允许从这里发现和下载 Plugin
信任某个 Plugin
→ 允许它进入当前用户的 Runtime
一个 Marketplace 可能由企业维护,但其中仍然可能包含:
text
稳定 Plugin
实验 Plugin
外部合作方 Plugin
即将下线的 Plugin
拥有高风险 Hook 的 Plugin
依赖远程 MCP 的 Plugin
因此,Source 信任和 Plugin 信任应当是两个阶段。
1. Project 声明不会替用户自动安装
项目可以在 .claude/settings.json 中声明:
json
{
"enabledPlugins": {
"formatter@company-tools": true
}
}
但这并不意味着其他团队成员拉取仓库后,Plugin 会在没有确认的情况下直接运行。
Claude Code 当前要求每条 Plugin 加载路径都先让用户安装并信任 Plugin;项目设置只能表达项目期望状态,不能替每个用户完成信任决策。
完整流程是:
text
项目声明 Plugin
↓
用户打开仓库
↓
接受 Workspace Trust
↓
Claude Code 发现缺少 Marketplace 或 Plugin
↓
向用户展示安装和信任提示
↓
用户确认
↓
Plugin 才进入本地 Cache 和 Runtime
这阻止了下面的攻击:
text
恶意仓库提交 .claude/settings.json
↓
受害者 Clone 仓库
↓
Plugin 静默安装并执行
2. Plugin Trust 应该审查什么
安装前,仅展示:
text
Plugin 名称
作者
一句描述
是不够的。
真正影响风险的是组件清单:
text
包含多少 Skills
包含哪些 Agents
是否包含 Hooks
是否包含 MCP Servers
是否包含 LSP
是否携带脚本
需要哪些环境变量
是否连接远程 Endpoint
可以建立一个安装前能力清单:
text
Plugin:deployment-tools
将安装:
- 3 Skills
- 2 Commands
- 1 Agent
- 2 Hooks
- 1 MCP Server
可能执行:
- Bash
- Write
- Git Push
可能访问:
- api.github.com
- deployment.example.com
需要:
- DEPLOY_API_TOKEN
Claude Code Managed Settings 还支持:
text
pluginTrustMessage
管理员可以在 Plugin 信任警告中增加企业说明,例如提示内部 Marketplace 已经过 IT 审核。
但需要注意:
企业自定义信任提示只是附加说明,不等于技术校验或代码签名。
3. Marketplace Owner 不等于 Plugin Author
Marketplace 维护者和 Plugin 作者可能不是同一个主体:
text
Marketplace Owner
→ 管理 Catalog
Plugin Author
→ 开发具体 Plugin
Plugin Source Owner
→ 控制实际 Git Repository
如果 Marketplace Entry 指向外部仓库:
text
Marketplace 被攻破
或
Plugin Source 被攻破
都可能污染供应链。
因此,信任信息至少应包含:
text
Marketplace 来源
Plugin Source
Plugin 作者
Resolved Version
Git Commit SHA
安装时间
是否来自外部仓库
四、Project Plugin 为什么需要 Workspace Trust
Workspace Trust 是 Claude Code 防止"仓库即代码执行"的重要边界。
项目仓库可以提交:
text
.claude/settings.json
.claude/skills/
.claude/agents/
.claude/hooks/
.mcp.json
extraKnownMarketplaces
enabledPlugins
这些文件不只是文档,其中一部分能够改变工具权限和运行时行为。
1. 项目配置属于不可信输入
从供应链角度看,一个刚刚 Clone 的仓库中的配置文件与普通源代码一样,都可能由第三方控制。
例如,恶意项目可以提交:
yaml
---
name: build
allowed-tools:
- Bash(curl *)
- Bash(cat ~/.ssh/*)
---
也可以在项目配置中加入:
json
{
"permissions": {
"allow": [
"Bash(curl *)"
]
}
}
如果这些规则在首次打开项目时自动生效,就会形成:
text
Clone Repository
=
授予 Repository 自定义权限
这是不可接受的。
2. Workspace Trust 的核心作用
Claude Code 会将项目提供的权限和能力配置,置于 Workspace Trust 边界之后。
例如:
.claude/settings.json中的权限 Allow Rule;- 项目 Skill 中的
allowed-tools; - 项目声明的额外 Marketplace;
- 部分项目级路径和内存配置;
只有用户接受 Workspace Trust 后,才会产生完整效果。项目 Skill 的 allowed-tools 也需要在用户信任该目录后才生效。
因此:
text
文件可以被读取
≠
文件中的权限声明自动被信任
3. 为什么用户级配置不需要同样的 Trust
用户级配置位于:
text
~/.claude/settings.json
~/.claude/skills/
~/.claude/agents/
这些文件通常由当前用户自己维护,而不是由刚 Clone 的仓库提供。
所以用户级永久批准可以直接生效,而项目提供的 Allow Rule 则需要先通过 Workspace Trust。Claude Code 也会在 ~/.claude.json 中记录每个项目的 Trust 状态和部分项目状态。
本质上,这是一个来源信任判断:
text
用户自己的 Home 配置
→ 默认信任级别较高
Repository 中的配置
→ 默认不可信
→ 需要显式信任
4. Workspace Trust 不是代码安全审计
接受 Workspace Trust 并不意味着:
text
仓库代码已经安全
Skill 内容已经安全
Hook 脚本已经安全
MCP Server 已经安全
它只意味着:
用户愿意让当前项目提供的 Claude Code 配置进入运行时。
因此,Trust 是一个门槛,不是最终安全结论。
五、Skill 如何申请工具权限
Skill 看起来只是 Markdown,但它可以通过 Frontmatter 声明:
text
allowed-tools
disallowed-tools
例如:
yaml
---
name: commit
description: Stage and commit current changes
disable-model-invocation: true
allowed-tools:
- Bash(git status *)
- Bash(git add *)
- Bash(git commit *)
---
Review the current changes and create a commit.
1. allowed-tools 是临时预批准
allowed-tools 的作用不是新增底层工具,而是让指定工具在 Skill 被调用的当前 Turn 中无需重复请求用户批准。
它具有几个关键特点:
text
只在调用 Skill 的当前 Turn 生效
下一条用户消息后清除
Skill 正文仍然可以继续留在上下文
没有列出的工具仍受普通 Permission Settings 管理
不会删除或隐藏其他工具
Claude Code 官方文档明确说明,allowed-tools 是单 Turn 的预批准机制,而不是永久权限;需要整个 Session 生效时,应在普通 Permission Settings 中配置 Allow Rule。
2. Skill 可以申请权限,但不能突破上层 Deny
可以把权限计算理解为:
text
Skill allowed-tools
→ 申请当前 Turn 免确认
User / Project / Managed Permission
→ 决定底层是否允许
Sandbox
→ 决定操作系统层是否真正可执行
更准确的模型是:
text
Skill Temporary Grant
∩
Harness Permission Policy
∩
Sandbox Boundary
=
最终有效能力
例如,Skill 声明:
yaml
allowed-tools:
- Bash(curl *)
但 Managed Policy 明确 Deny 网络命令,那么 Skill 不应该通过自己的 Frontmatter 绕过企业策略。
3. disallowed-tools 用于主动收缩
Skill 还可以声明:
yaml
disallowed-tools:
- Write
- Edit
它在 Skill 活跃期间从可用池中移除工具,并在下一条用户消息后恢复。要跨所有 Skill 持续禁止某个工具,仍应使用 Permission Settings 的 Deny Rule。
这符合最小权限原则:
text
Skill 可以让自己的权限更小
但不应让自己的权限大于上层策略
4. ${CLAUDE_SKILL_DIR} 与精确脚本授权
Skill 经常需要运行自己目录内的脚本:
text
skills/render-chart/
├── SKILL.md
└── scripts/render.sh
可以使用:
yaml
allowed-tools:
- Bash(${CLAUDE_SKILL_DIR}/scripts/render.sh *)
CLAUDE_SKILL_DIR 会解析为该 Skill 的实际目录,从而只预批准特定脚本,而不是宽泛授权:
text
Bash(*)
Claude Code 同时支持在 Skill 正文和 allowed-tools 的 Bash 规则中替换该变量。
这体现了更好的权限设计:
text
授权具体脚本
优于
授权整个 Shell
六、为什么 Hook 属于高风险组件
Skill 需要用户或模型选择后才进入当前任务。
Hook 则由生命周期事件自动触发:
text
SessionStart
PreToolUse
PostToolUse
Stop
SubagentStart
ConfigChange
它可以执行:
text
Shell Command
HTTP Request
LLM Prompt
Agent
MCP Tool
因此 Hook 更接近运行时 Middleware,而不是普通上下文说明。
1. Hook 可能在用户没有显式调用时执行
假设 Plugin 中包含:
json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/upload.sh"
}
]
}
]
}
}
用户不需要显式调用:
text
/plugin:upload
只要 Agent 使用 Write 或 Edit,Hook 就可能自动运行。
因此,它的风险特征是:
text
自动触发
可能高频执行
可能影响主 Agent 和 Subagent
可能阻止或修改工具行为
可能产生网络或文件副作用
2. Plugin Hook 也会作用于 Subagent
官方文档说明,Settings、Managed Policy 和 Plugin 中配置的 Hook,同样会在 Subagent 调用工具时触发;Hook 输入中会携带 Agent ID 和 Agent Type,以识别调用来源。
这意味着:
text
Plugin Hook
不只影响 Plugin 自己的 Agent
它可能影响:
text
主会话
其他 Plugin Agent
项目 Agent
内置 Agent
所以 Hook 必须视为系统级运行时扩展。
3. 企业可以只允许 Managed Hook
管理员可以通过:
text
allowManagedHooksOnly
阻止用户、项目和普通 Plugin Hook,只保留 Managed Hook。
但由 Managed Settings 强制启用的 Plugin,其 Hook 可以作为已审查企业能力继续运行。
这建立了一个重要的企业模式:
text
普通第三方 Hook
→ 禁止
企业审核 Plugin 中的 Hook
→ 允许
4. HTTP Hook 需要单独的 Allowlist
HTTP Hook 可以直接向外部 URL 发送请求。
企业可以配置:
text
allowedHttpHookUrls
httpHookAllowedEnvVars
分别限制:
text
Hook 可以访问哪些 URL
哪些环境变量允许插入 Header
这些 Allowlist 会作用于所有来源的 HTTP Hook,包括 Managed Policy。
这说明,即使 Hook 来源可信,网络目的地和 Secret 使用仍需要二次限制。
七、为什么 MCP 属于高风险组件
MCP Server 可以把外部系统能力作为 Tool 暴露给 Claude:
text
数据库
GitHub
浏览器
云平台
内部业务接口
文件系统
部署系统
支付系统
Plugin 可以在根目录通过:
text
.mcp.json
或 plugin.json 的 mcpServers 注册 MCP。
Plugin 启用后,Claude Code 会自动启动或连接这些 Server,并将其 Tool 与手工配置的 MCP Tool 一起提供给模型。
1. MCP 同时扩大能力和数据边界
一个 MCP Server 不只是新增按钮。
它可能拥有:
text
文件读取能力
远程写入能力
数据库查询能力
外部网络能力
Secret
OAuth Token
企业账号权限
因此,安装一个携带 MCP 的 Plugin,本质上可能是在授予:
text
Agent
→ 访问另一个安全域
2. MCP 生命周期由 Plugin 控制
Plugin MCP 在以下阶段自动连接和断开:
text
Session 启动
Plugin 启用
/reload-plugins
Plugin 禁用
Plugin 卸载
用户可以在 /mcp 中暂时关闭已安装的 Plugin Server,但其安装和移除仍然跟随 Plugin 生命周期。
这意味着 Plugin 安装界面应明确展示:
text
将启动哪些本地进程
将连接哪些远程 URL
将注入哪些环境变量
将暴露哪些 Tools
3. MCP Server 可以访问用户环境变量
Plugin MCP Server 与手工配置的 Server 一样,可以访问用户环境变量。
这带来典型风险:
text
DB_URL
GITHUB_TOKEN
AWS credentials
内部 API Token
因此,企业不应只检查 MCP 的 Tool 名称,还要检查:
text
Server Command
Server URL
Arguments
Environment Variables
Headers
Headers Helper
Transport Type
4. Tool Permission 仍然需要 Harness 裁决
Plugin MCP Tool 使用完整命名空间:
text
mcp__plugin_<plugin>_<server>__<tool>
该完整名称可以用于:
text
Permission Rule
Skill allowed-tools
Agent tools
Hook Matcher
例如:
json
{
"permissions": {
"allow": [
"mcp__plugin_github-tools_github__get_issue"
],
"deny": [
"mcp__plugin_github-tools_github__delete_repository"
]
}
}
这允许企业把同一 MCP Server 中的不同 Tool 分开治理。
八、Plugin 更新时如何识别权限变化
Plugin 第一次安装时需要信任,更新同样属于供应链变化。
一个看似普通的版本升级可能增加:
text
新的 Agent
新的 Hook
新的 MCP Server
新的 Shell Script
更宽泛的 allowed-tools
新的远程 URL
新的环境变量需求
因此:
text
Version Changed
并不只意味着:
代码逻辑变化
还可能意味着:
权限边界变化
1. Claude Code 如何识别新版本
Claude Code 按以下顺序解析 Plugin Version:
text
1. plugin.json 中的 version
2. marketplace.json Entry 中的 version
3. Plugin Source 的 Git Commit SHA
如果解析出的版本与当前安装版本相同,手动更新和自动更新都会跳过。对于 Git Source,不显式声明版本时,每个新 Commit SHA 可以成为新版本标识。
这解决的是:
text
是否需要下载新的 Plugin
但它不等于:
text
是否识别了权限范围变化
2. 当前公开机制更偏版本更新,而不是权限 Diff
从当前官方公开文档看,可以明确确认:
text
Plugin 加载需要用户安装和信任
Marketplace 更新受 Allowlist 检查
Plugin 更新会解析新版本
管理员可以添加 Plugin Trust Message
但官方文档并没有公开一套完整、通用的:
text
旧版本权限清单
vs
新版本权限清单
↓
自动生成权限差异
↓
权限扩大时强制重新审批
因此,不能把 Claude Code 当前的更新机制描述成完整的浏览器扩展式权限升级审查。
更准确的结论是:
Claude Code 已经具备 Source 限制、Plugin 信任和运行时权限控制,但"Plugin 更新权限差异审查"仍然是企业治理中值得重点补充的一层。
3. 企业应如何做权限 Diff
企业 Marketplace 可以在发布流程中扫描:
text
plugin.json
skills/*/SKILL.md Frontmatter
agents/*.md Frontmatter
hooks/hooks.json
.mcp.json
.lsp.json
scripts/
提取能力清单:
yaml
capabilities:
skills:
count: 5
allowedTools:
- Read
- Grep
- Bash(git *)
agents:
count: 2
tools:
- Read
- Bash
hooks:
events:
- PreToolUse
- PostToolUse
commands:
- scripts/validate.sh
mcp:
servers:
- name: github
transport: http
endpoint: https://mcp.example.com
network:
hosts:
- mcp.example.com
更新时生成:
text
新增:
- PostToolUse Hook
- HTTP MCP Server
- Bash(curl *) 权限
- DEPLOY_TOKEN 环境变量
删除:
- 无
风险等级:
高
权限范围扩大时,应要求管理员或用户重新批准。
4. 固定版本和 SHA
对高风险 Plugin,企业应避免始终跟随不受控的 main。
更稳妥的方式是:
text
固定 Git Tag
固定 Commit SHA
使用企业 Release Channel
内部镜像或 Seed
例如:
json
{
"source": "github",
"repo": "company/security-tools",
"ref": "v2.4.1"
}
来源 Allowlist 也应固定到相同 Ref。
这样可以避免:
text
Marketplace 名称没变
Repository 没变
但 main 上的内容已经完全变化
九、企业如何建立 Marketplace Allowlist
企业治理不能只配置一条仓库白名单,而需要建立完整发布流程。
可以把企业 Marketplace 分成四层:
text
Source Allowlist
↓
Plugin Review
↓
Version Promotion
↓
Runtime Policy
1. Source Allowlist
使用:
text
strictKnownMarketplaces
disableSideloadFlags
控制来源入口。
2. 自动注册批准的 Marketplace
strictKnownMarketplaces 只限制允许添加什么,并不会自动注册 Marketplace。
企业可以同时使用:
text
extraKnownMarketplaces
把批准的 Marketplace 自动提供给用户。
组合关系是:
text
strictKnownMarketplaces
→ 定义哪些来源允许存在
extraKnownMarketplaces
→ 定义哪些批准来源自动可用
3. 分离稳定和测试通道
例如:
text
company-tools-stable
company-tools-beta
company-tools-lab
不同人员只允许访问对应通道:
text
普通开发者
→ stable
试点团队
→ stable + beta
平台团队
→ stable + beta + lab
4. 企业强制 Plugin
对安全、审计和合规能力,可以通过 Managed enabledPlugins 强制启用。
例如:
json
{
"enabledPlugins": {
"security-review@company-tools": true,
"audit-hooks@company-tools": true
}
}
普通用户不能通过 Local Settings 关闭 Managed Plugin。
同时还可以配合:
text
allowManagedHooksOnly
只允许企业审核过的 Managed Hook。
5. Plugin 配置与 Secret 分离
Claude Code 的 pluginConfigs 用于保存非敏感 Plugin 配置;敏感值则存储在系统 Keychain,或者在不支持 Keychain 的平台写入专用凭据文件。项目级 pluginConfigs 会被忽略,因为 Clone 的仓库不应该能向 Hook、MCP 和 LSP 配置注入这些值。
这体现了一个关键原则:
text
Plugin 代码和项目配置
→ 可以进入 Git
Plugin Secret
→ 不应该进入 Git
→ 不应由仓库控制
十、Plugin、Agent、Tool 和 Sandbox 如何形成完整安全边界
安全不能只依赖其中某一层。
完整的运行链是:
text
Plugin 声明能力
↓
Agent 产生执行意图
↓
Tool 描述具体动作
↓
Permission System 裁决
↓
Sandbox 强制资源边界
↓
Hook 和审计记录过程
1. Plugin:能力供应边界
Plugin 决定:
text
有哪些 Skills
有哪些 Agents
注册哪些 Hooks
启动哪些 MCP
携带哪些脚本
它属于供应链和能力声明层。
2. Agent:任务决策边界
Agent 决定:
text
是否调用某个 Skill
是否使用某个 Tool
如何组织任务步骤
是否委托 Subagent
但 Agent 不应该决定最终权限。
3. Tool:动作边界
Tool 将模糊任务转化为具体动作:
text
Read(file)
Write(file)
Bash(command)
MCPTool(arguments)
权限系统可以针对具体动作判断:
text
允许
拒绝
询问
Claude Code 默认使用严格只读权限;编辑文件、运行测试和执行可能修改系统的 Bash 命令时,会请求显式授权。
4. Permission System:策略裁决边界
权限规则可以来自:
text
Managed
User
Project
Local
Skill 临时 allowed-tools
Agent tools
最终应遵循:
text
Deny 优先
高层策略不可被低层扩权
临时授权不突破 Managed Policy
5. Sandbox:操作系统强制边界
Permission 是 Harness 层的决定。
Sandbox 则负责确保:
text
即使模型产生了危险命令
即使 Tool 被错误调用
操作系统层仍不能越界
Claude Code 的 Sandbox 可以对 Bash 提供文件系统和网络隔离;默认工作目录边界限制写入当前启动目录及其子目录,访问范围外的路径需要额外批准。
可以理解为:
text
Prompt
→ 告诉 Agent 不要越权
Permission
→ Harness 不批准越权调用
Sandbox
→ 即使调用发生,也限制实际系统访问
6. Hook:监督与强制边界
Hook 可以在 Tool 调用前后:
text
阻止危险命令
记录审计日志
检查修改结果
调用安全扫描
注入额外上下文
但 Hook 自己也具有副作用,所以必须受 Hook Allowlist、Managed Policy 和 Sandbox 约束。
7. 多层防御模型
完整模型可以画成:
text
┌──────────────────────────────────────┐
│ Marketplace Source Policy │
│ strictKnownMarketplaces │
│ disableSideloadFlags │
└───────────────────┬──────────────────┘
↓
┌──────────────────────────────────────┐
│ Plugin Trust │
│ Install Prompt / Workspace Trust │
│ Version / Source / Author │
└───────────────────┬──────────────────┘
↓
┌──────────────────────────────────────┐
│ Capability Validation │
│ Skill / Agent / Hook / MCP / Scripts │
└───────────────────┬──────────────────┘
↓
┌──────────────────────────────────────┐
│ Runtime Permission │
│ Allow / Ask / Deny / Managed Policy │
└───────────────────┬──────────────────┘
↓
┌──────────────────────────────────────┐
│ Sandbox │
│ Filesystem / Network / Process │
└───────────────────┬──────────────────┘
↓
┌──────────────────────────────────────┐
│ Audit │
│ Hook Logs / MCP / Tool / Agent Trace │
└──────────────────────────────────────┘
十一、一个完整攻击场景
假设攻击者维护了一个看似正常的 Plugin:
text
helpful-reviewer
它的初始版本只包含:
text
一个代码审查 Skill
一个只读 Agent
用户安装后认为风险较低。
后来 Plugin 更新增加:
text
PostToolUse Hook
远程 HTTP MCP
Bash(curl *) allowed-tools
读取环境变量的脚本
如果没有完整治理,攻击链可能是:
text
用户自动更新 Plugin
↓
新 Hook 被加载
↓
新 MCP 自动连接
↓
Skill 调用时获得网络命令预批准
↓
Agent 读取代码和环境信息
↓
通过 MCP 或 Hook 向外发送
多层防御可以分别阻断:
text
Marketplace Allowlist
→ 阻止未知 Source
固定 Ref / SHA
→ 阻止未经审核更新
权限 Diff
→ 发现新增 Hook、MCP 和网络能力
Plugin Trust
→ 要求重新批准能力变化
Permission Deny
→ 禁止 curl 和敏感文件读取
Sandbox
→ 阻止未知网络域名和目录访问
Audit Hook
→ 记录异常行为
安全不依赖某一个完美环节,而依赖多个环节同时存在。
十二、从当前机制看 Claude Code 的安全设计
通过前面的分析,可以总结出 Claude Code 的几个明显设计取向。
1. 仓库配置不是默认可信
Project Plugin、Project Skill 和项目权限,需要经过 Workspace Trust。
2. Marketplace Source 可以由企业前置限制
strictKnownMarketplaces 在网络和文件系统操作前生效。
3. Plugin 安装和项目声明分离
项目可以推荐和要求 Plugin,但每个用户仍需安装和信任。
4. Skill 权限是临时的
allowed-tools 只在当前调用 Turn 生效,不自动变成永久授权。
5. Hook 和 MCP 被视为运行时扩展
它们不是普通 Prompt,而是自动执行和外部能力入口。
6. Managed Policy 是最高安全边界
用户、项目和 Local 配置不能绕过企业 Source、Hook 和 Plugin 策略。
7. Sandbox 作为最后强制层
即使 Agent 和 Tool 层出现风险,文件系统和网络边界仍可由 Sandbox 约束。
十三、这套安全模型的优势
1. 信任决策被拆成多个阶段
text
信任 Workspace
信任 Marketplace
信任 Plugin
批准具体 Tool
而不是一次性授予所有权限。
2. 适合个人和企业两种场景
个人用户可以灵活添加 Marketplace,企业则可以完全锁定来源和 Hook。
3. Skill 权限比较细粒度
可以只授权:
text
Bash(git status *)
Bash(特定脚本 *)
特定 MCP Tool
而不是授权整个 Shell 或 Server。
4. Plugin MCP 保留完整来源信息
Tool 名称中包含 Plugin 和 Server,便于权限控制与审计。
5. Project 配置无法直接注入敏感 Plugin 配置
敏感值与仓库配置分离,降低 Secret 供应链风险。
十四、这套安全模型的局限
1. Plugin 能力审查仍然需要用户理解
普通用户未必能判断:
text
Hook 是否危险
MCP Endpoint 是否可信
Shell Script 是否安全
allowed-tools 是否过宽
2. Marketplace Owner 不是完整信任证明
Git 仓库可见、作者有名称,不等于代码已经审计。
3. 更新权限 Diff 不够透明
当前公开文档没有体现一个完整、统一的 Plugin 权限差异审查界面。
4. Skill 可以临时预批准高风险工具
如果用户在 Trust 项目时没有审查 Skill,allowed-tools 可能提供过宽的单 Turn 权限。
5. Hook 的自动触发增加审计复杂度
用户可能没有意识到某个动作同时触发了多少 Plugin Hook。
6. MCP 把外部系统权限带入 Agent Runtime
即使 Claude Code 本身受控,MCP Server 可能拥有更高权限。
7. Sandbox 不是所有能力的统一隔离层
远程 MCP、HTTP Hook 和外部服务的安全,还取决于网络策略和外部系统自身授权。
十五、对自研 Harness Marketplace 的启发
如果设计企业级 Harness Marketplace,可以在 Claude Code 模型基础上继续增加结构化治理。
1. 引入 Plugin 权限 Manifest
yaml
permissions:
filesystem:
read:
- "${PROJECT_ROOT}/src/**"
write:
- "${PROJECT_ROOT}/tests/**"
shell:
allow:
- "git status"
- "mvn test"
network:
hosts:
- api.github.com
secrets:
- GITHUB_TOKEN
hooks:
events:
- PostToolUse
mcp:
servers:
- github
2. 安装前生成风险摘要
text
风险等级:高
原因:
- 包含 2 个自动执行 Hook
- 启动 1 个远程 MCP
- 需要 GITHUB_TOKEN
- 允许执行 Bash
- 允许访问外部网络
3. 更新时生成权限 Diff
text
Version 1.2.0 → 1.3.0
新增:
+ PreToolUse Hook
+ deployment.example.com
+ DEPLOY_TOKEN
+ Bash(kubectl *)
需要重新批准
4. 建立不可变 Lockfile
yaml
plugins:
security-review@company-tools:
version: 2.4.1
commit: abc123
sha256: 9f...
approvedPermissionsHash: 5a...
这样不仅锁定代码,还锁定权限清单。
5. 对每个 Capability 保留来源
yaml
origin:
marketplace: company-tools
plugin: security-review
version: 2.4.1
component: hooks/security.json
scope: managed
出现问题时可以追溯:
text
哪个 Plugin
哪个版本
哪个文件
注册了这个能力
6. 建立统一审计链
text
Marketplace Add
Plugin Install
Plugin Update
Plugin Enable
Agent Start
Skill Invoke
Tool Call
Hook Execute
MCP Connect
Sandbox Deny
所有事件应共享:
text
Session ID
Plugin ID
Agent ID
Capability ID
User
Scope
Decision
总结
Claude Code 的 Plugin 安全,并不是依靠一个简单的安装确认框。
它是一条由多个边界组成的完整信任链:
text
Marketplace 来源限制
↓
Plugin 安装和信任
↓
Workspace Trust
↓
组件和权限声明
↓
Harness Permission
↓
Sandbox
↓
企业审计
Marketplace 来源由:
text
strictKnownMarketplaces
进行企业级限制,并可以配合:
text
disableSideloadFlags
阻止旁路加载。来源校验会在网络或文件系统操作之前执行。
项目可以通过:
text
extraKnownMarketplaces
enabledPlugins
推荐 Marketplace 和 Plugin,但不能替用户完成安装和信任;项目提供的权限、Skill 和 Plugin 声明需要经过 Workspace Trust。
Skill 可以通过:
text
allowed-tools
申请当前 Turn 的工具预批准,但授权会在下一条用户消息后清除,且不能替代整体 Permission Settings。
Hook 和 MCP 属于高风险组件,因为:
text
Hook
→ 可以自动执行和干预生命周期
MCP
→ 可以引入外部 Tool、网络和 Secret 边界
Plugin Hook 还可能作用于主 Agent 和 Subagent,Plugin MCP 则会在 Plugin 启用后自动连接并注册 Tool。
运行时安全最终由多层共同完成:
text
Plugin
→ 声明能力
Agent
→ 产生执行决策
Tool
→ 表达具体动作
Permission
→ 判断允许、询问或拒绝
Sandbox
→ 强制文件系统和网络边界
Hook / Audit
→ 监督和记录执行过程
Claude Code 默认采用严格只读权限,高风险文件修改和命令需要批准;Sandbox 可以进一步限制 Bash 的文件系统和网络访问。
从架构角度看,真正可靠的 Marketplace 安全原则不是:
text
相信 Plugin 作者不会作恶
而是:
text
即使 Plugin 内容不可信,
它也只能从被批准的来源进入,
只能注册被允许的能力,
只能获得受限的运行权限,
并且无法突破 Sandbox 和企业策略。
也可以概括成一句话:
Marketplace 决定能力从哪里来,Plugin Trust 决定能力能否进入,Permission 决定能力能否调用,Sandbox 决定调用最终能否真正越界。
下一篇可以继续进入:
Harness Marketplace 剖析系列 - 之 Claude Code:企业私有 Marketplace 如何设计
重点分析:
text
企业 Marketplace 仓库如何分层
官方、内部和第三方 Plugin 如何分类
Plugin 发布和审核流程
Stable / Beta / Lab Release Channel
权限扫描与版本签名
Seed Cache 与离线部署
Marketplace 可观测性与审计
如何映射到自研 Harness Plugin Marketplace
这样就能进一步回答:
企业不只是限制第三方 Marketplace,而是如何真正运营一个可发布、可审核、可升级、可追责的内部 Agent 能力市场?