VS Code AI 扩展:管理代码入口、网络出口与退出动作
一次真实的开发事故可以从一条“安装并登录即可”的建议开始。开发者在陌生仓库里安装了 AI 扩展,点击信任工作区,扩展随即读取项目、启动语言服务、请求网络并把认证状态写进本机 Secret Storage;另一款补全扩展也在运行,两者同时改写建议、发出遥测、争夺同一快捷键。后来排查构建失败时,团队才发现某个扩展安装在远端 extension host,而 token 留在本地 profile,禁用其中一个后行为仍在。安装页面没有错,工程链却没有任何可证明的边界。
VS Code 的 AI 能力不是一个产品按钮,而是若干扩展、账户、模型服务、聊天代理、语言服务、终端与远端开发位置共同组成的系统。扩展可以显示聊天、读取文本、创建文件、调用命令、连接网络、保存认证状态、启动子进程,甚至把工具调用交给代理。无论扩展宣传的是补全、代码审查、文档生成还是 Agent,它首先都是运行在开发环境中的软件供应链对象;先治理包和权限,再讨论回答质量。
先盘点已经运行的扩展,而不是立即再装一个
事故恢复与新工具试用都从清单开始。在隔离 Profile 中打开一份脱敏仓库,保留默认 VS Code 之外只安装一项测试扩展;不要使用平日登录过代码托管、云平台或公司单点登录的 Profile。先导出当前扩展 ID 和版本,记录 IDE 版本、安装渠道、操作系统、工作区是否可信、是否使用 Remote SSH、WSL、容器或 Web。AI 扩展的显示名会变化,唯一的 publisher.extension 与版本才便于重建和审查。
code --version
code --list-extensions --show-versions | Sort-Object |
Set-Content -Encoding utf8 .\extensions-before.txt
code --statuscode --status 有助于观察 extension host、进程与资源状态,但报告可能包含机器路径、代理、环境或扩展信息,进入工单前应脱敏。清单也要区分内置扩展、用户安装扩展、远端安装扩展和由 Profile 同步恢复的扩展。一个本机命令看不到远端容器或 SSH 主机上的所有状态时,不要把“列表为空”误作“没有扩展”。
再查看扩展详情:发布者、唯一 ID、版本、许可证、更新记录、仓库、隐私说明、是否需要登录、声明的语言和命令。看见相似名称时不要凭图标或下载量判断身份。官方 Marketplace 对包分发提供签名和发布者信任提示,这证明来源和传输完整性,不保证扩展没有漏洞、不会发起网络请求,也不等于其依赖或模型供应商已经被组织批准。
正向实验只选一项不需要真实账号、不执行命令、不修改工作区的扩展功能。安装后验证它的一个可见能力,再导出 extensions-after.txt 并比较;预期新增项只有批准 ID 与批准版本。反向实验使用一个故意写错的 ID 或被策略阻断的 ID;预期安装命令明确失败或扩展显示被禁用。若未知 ID 安装成功,或一次安装连带出现多个未登记的扩展、helper、账户提示,应停止试验并检查 extension pack、Profile 同步和组织策略。
安装来源、签名与更新是一条连续供应链
从 Extensions 视图搜索安装、用 code --install-extension 安装、加载 .vsix 文件和由组织预装,都是不同来源路径。团队应在批准记录中保存扩展 ID、发布者、版本、安装包来源、许可证、依赖/extension pack、适配平台、owner、网络目的地与退出动作。Marketplace 会做恶意软件、秘密和签名检查,VS Code 安装时也会验证 Marketplace 签名,但这些是供应链证据,不是运行时沙箱。官方 Extension runtime security 明确指出,extension host 与 VS Code 本身拥有相同权限,扩展可以读写文件、发起网络请求、启动外部进程和修改工作区设置;因此扩展仍应按拥有开发者用户权限的软件看待。
# 仅替换为批准记录中的 ID 与固定版本
$extension = 'publisher.extension@1.2.3'
code --install-extension $extension
# 本地离线包也应来自已验证的内部制品库
code --install-extension .\approved\publisher.extension-1.2.3.vsix从 VSIX 安装时,官方 Extension Marketplace 文档 说明该扩展默认不会自动更新。这适合受控回归与回滚,也意味着漏洞修复不会自动到达,必须有升级巡检。Marketplace 自动更新则带来相反风险:未经代表仓库验证的版本可能在设备间逐渐漂移。将 AI 扩展纳入更新窗口,先在隔离 Profile 与代表项目中检查启动、索引、登录、补全、聊天、diff、测试、网络和性能,再扩大推广;有问题时禁用问题版本、恢复保留的包或版本,并锁住策略。
{
"extensions.autoUpdate": false,
"extensions.autoCheckUpdates": true,
"extensions.autoUpdateDelay": 24
}这是示意的个人设置,不会阻止组织策略覆盖它,也不会钉住一个允许版本。受管设备应以组织策略和批准清单为准。升级后如果 VS Code 要求重启 extension host,重启前保存未提交编辑、重启后再次导出清单并运行最小测试;不要把“更新按钮消失”理解为功能验证完成。旧 VSIX、哈希、兼容的 VS Code 版本和配置备份必须在升级之前保存,否则“回滚”只是一句没有介质的承诺。
Workspace Trust 约束工作区执行,不能把扩展变成沙箱
Workspace Trust 的目标是让你决定项目目录里的代码能否驱动 VS Code 与扩展执行。陌生压缩包、临时下载、外部贡献分支和未知多根工作区都应先以 Restricted Mode 打开。官方 Workspace Trust 文档 明确,受限模式下仍可浏览和编辑代码,而不支持信任的扩展会被禁用或限制;工作区任务、调试、某些设置和扩展能力也可能不工作。这使它适合做第一道“不要急着执行”的门,而不是数据防泄漏工具。
{
"security.workspace.trust.enabled": true,
"security.workspace.trust.emptyWindow": false,
"security.workspace.trust.untrustedFiles": "newWindow",
"security.workspace.trust.startupPrompt": "once"
}正向实验:从一个不可信目录打开虚构仓库,保持 Restricted Mode,确认任务、调试和 AI 扩展的受限状态可见;只阅读源码和配置,不执行推荐任务。审查仓库来源、.vscode 内容和依赖脚本后,选择信任,再验证原先被限制的功能是否恢复。预期信任改变的是该工作区执行权限,不是给所有扩展授予更高的系统权限。
反向实验:对一个不支持不可信工作区的 AI 扩展,强行加入 extensions.supportUntrustedWorkspaces 覆盖项。预期 VS Code 会显示该选择与版本有关,并且扩展可能恢复能力;这正是应当被记录为风险升级的证据,而不是普通兼容修复。不要用 --disable-workspace-trust 作为日常启动方式,它只影响当前会话,也会绕开最有价值的陌生项目防线。更重要的是,Workspace Trust 依赖扩展声明和扩展代码主动遵守,官方明确说明它不能阻止恶意扩展忽略 Restricted Mode;扩展准入、发布者信任、系统权限和网络治理仍是独立控制层。
Extension Host 的位置决定代码、网络与日志从哪里发生
“扩展运行在 VS Code 里”不够精确。官方 Extension Host 架构说明 区分本地 Node.js host、Web Worker host 和远端 Node.js host。桌面 VS Code 可能同时运行本地与 web host;使用 SSH、容器、WSL、Codespaces 或 Tunnel 时,还可能有远端 host。扩展会根据它声明的 extensionKind、入口点、可用运行时、安装位置和工作区位置选择运行处。于是同一 AI 扩展的文件访问、子进程、代理环境、网络出口、缓存和日志位置都可能不同。运行在远端 Node.js host 的扩展继承的是远端 VS Code Server 进程能够使用的账号和网络,不会自动受本地终端的代理、密钥库或应用控制策略保护。
先在状态栏或 Remote Explorer 确认当前窗口连接位置,再在 Extensions 视图观察扩展是 Local 还是 Remote。一个需要访问远端工作区并运行远端工具的扩展若只装在本地,可能功能缺失;一个会读取工作区的扩展装在远端,则其网络访问和缓存不在本机。不能为了让功能出现就把同一 AI 扩展同时装在两端而不做盘点,因为这会增加两个运行实体、两份配置和潜在的两个数据出口。
# 在本地窗口和远端窗口分别运行并保存脱敏输出
code --status
code --list-extensions --show-versions
# 由 VS Code 命令面板执行:Developer: Show Running Extensions正向实验使用一个没有真实密钥的远端测试目录:仅安装批准扩展到需要的位置,调用一次只读功能,查看 Running Extensions 的 host、激活耗时和 CPU;预期文件访问和终端命令都发生在事先选择的位置。反向实验故意只把依赖远端工作区的扩展安装到另一侧,预期出现无法激活、无法找到工具或明确位置提示;正确处理是补全经过批准的安装位置或改用兼容扩展,而不是复制 token、关闭信任或把远端目录映射到不受控位置。
多个 host 还会让故障更像“随机”。本地扩展更新、远端扩展未更新,或一个扩展在 UI host 读取设置而另一个在 workspace host 执行命令,都能造成版本与行为分叉。排查应同时收集窗口日志、extension host 日志、运行扩展列表、连接目标和版本清单;只截图本地 Extensions 页面无法证明远端是否仍有旧插件运行。
凭据、Secret Storage、网络与代理必须分别管理
AI 扩展常把登录状态、OAuth 刷新令牌或 API key 存入 VS Code 的 Secret Storage。官方 SecretStorage API 将它定义为扩展私有的加密存储,并明确秘密不会随设置同步到其他机器。它比把秘密写入 settings.json、工作区配置或 Git 更好,却不是团队秘密库,也不限制扩展取得秘密后向哪里发送。秘密位于本地还是远端,还取决于扩展实际运行的 host;登录页面在本机打开,并不能证明 token 只保存在本机。每个扩展只使用组织批准的账户方式,且 token 采用最小权限、可撤销、可审计的短生命周期授权;不得为了让聊天工作把个人长期 key 写进 .vscode/settings.json、tasks.json、shell profile、提示词、测试 fixture 或 issue。
{
"aiExtension.example.endpoint": "https://api.example.invalid",
"aiExtension.example.token": "${env:AI_EXTENSION_TOKEN}",
"http.proxyStrictSSL": true
}这段配置只表达结构:端点是公开的占位地址,token 从受控环境取得,不能填真实值,也不保证任意扩展会解析 ${env:...}。安装前必须读扩展自己的官方配置文档,确认它支持的认证方式;不支持安全注入的扩展不应通过在配置文件中明文放 key 来“兼容”。不把 secret 提供给扩展也是有效选择。
网络审查要区分 VS Code 更新、Marketplace、扩展自身 API、模型供应商、遥测、OAuth、远端 host 与 MCP 工具。系统代理、证书拦截和允许域名可能让扩展报“无法登录”,但排障不该通过关闭 TLS 校验、全局代理所有流量或把证书私钥发给聊天来完成。先检查允许的域名、代理认证、证书链和网络日志,使用虚构账户验证最小请求;扩展需要访问未登记域名、上传完整工作区或启动本地监听端口时,停止扩权并走安全审查。
反向实验可以在隔离网络中撤销测试 token,再调用扩展的无副作用请求。预期认证明确失败,且不会改写项目文件或反复弹出浏览器登录;随后从扩展注销、删除测试 Secret Storage 条目或撤销 OAuth 授权,重启窗口后预期仍需重新认证。若卸载扩展后账户仍然可用,说明凭据可能留在系统密钥库、浏览器会话、远端 host 或另一个同类扩展中,必须继续盘点,不能用“已卸载”结束事件。
AI 扩展准入要审查实际能力,而不是做排行榜
对于每一项候选扩展,先写清其要解决的具体问题:补全、选中代码解释、受控聊天、代码审查,还是多步骤代理。再审查其实际能力:会否读取未打开文件、是否索引整个仓库、是否执行终端命令、是否能调用 Git、浏览器、MCP 或远端服务、上下文发往哪里、模型与账户由谁提供、日志和遥测保留在哪里、如何禁用与删除。VS Code 内置 Agent 的工作区文件限制、工具选择器、会话级审批、终端沙箱和 MCP 信任提示只描述内置能力,不能外推为所有第三方 AI 扩展的共同保护;第三方扩展仍按自己的实现、隐私条款和运行 host 单独验证。功能相近的扩展只保留一个 owner 明确的实现;同时装多个补全或 Agent 扩展,常造成重复请求、冲突建议、重复索引、快捷键覆盖和不可解释的成本。
可将批准对象分级。只读、无登录、无网络的编辑辅助仍需来源和更新审查;读取工作区并发往云端的聊天需要数据处理和账号审查;能够运行命令、写文件、调用外部工具或接入生产系统的代理则需要更高门槛,包括受控工作区、逐次工具确认、禁止自动提交/推送、最小 MCP 权限和独立人工审查。发布者知名、安装量高或图标带认证标记都不改变这个分级。
候选扩展:publisher.extension
用途:仅对选中代码生成解释与测试建议。
允许:读取手工附加文件;访问批准的认证与模型域名。
禁止:自动索引 secrets/、执行终端、写入 Git、调用 MCP、上传日志。
验证:隔离 Profile 中生成建议,人工应用一个补丁,运行项目测试并检查网络日志。
退出:禁用扩展、注销账户、撤销 token、删除远端副本、复核清单。扩展提供的权限说明不能替代实测。用脱敏代表仓库做正向实验:先关闭 Agent 写入与终端权限,只使用解释能力;再在明确允许的单文件上开启编辑,检查 Diff;最后运行原有测试。每一步都导出扩展清单、记录 host、网络目标与实际命令。反向实验让代理请求读取忽略目录、执行发布命令或访问未批准 MCP server;预期是拒绝、确认框或明确不可用。若它自动成功,立即禁用扩展,撤销测试身份并扩大事故排查,而非继续观察“会不会只改这一次”。
冲突通常发生在扩展、设置、语言服务和账号之间
AI 扩展异常不一定是模型服务故障。多个扩展可以注册同一语言、聊天 participant、命令、code action、格式化器、终端 profile、代理设置、快捷键或文件监听器。它们还可能各自维护索引与登录状态。典型表现包括补全闪烁、建议重复、保存后反复修改、CPU 飙升、聊天按钮消失、代理使用了另一个账号,或一个扩展的网络错误被另一个扩展掩盖。
排查先隔离变量:复制一个 Profile,只保留内置扩展和单一候选扩展;在同一脱敏仓库、同一工作区信任状态、同一网络环境中重试。VS Code 的 Help: Start Extension Bisect 能帮助定位哪项扩展触发问题;Developer: Show Running Extensions 用于观察激活与耗时;Window 和 Extension Host 日志可揭示加载、认证或 API 错误。不要先删除整个用户目录,这会毁掉能证明冲突来源的配置和日志。
{
"[typescript]": {
"editor.defaultFormatter": "publisher.approved-formatter"
},
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"workbench.settings.applyToAllProfiles": []
}这类设置应在团队中声明清楚作用域:用户、Profile、工作区、远端还是组织策略。不要把格式化器或聊天扩展 ID 填成未批准对象,也不要让工作区 settings 强迫每位成员安装插件。反向证据是设置在某 Profile 生效、换 Profile 消失,或组织策略显示被覆盖;此时检查 Setting 的来源和 Policy Diagnostics,区分“配置写错”“配置被策略覆盖”“扩展根本不在正确 host”三种情况。
删除一个扩展后问题没有消失时,逐项检查同类扩展、内置功能、远端 host、独立 CLI、浏览器插件和同步恢复。冲突消除的证据不是 UI 少了一个图标,而是单一扩展基线恢复预期行为、资源下降、网络目标收敛、测试与 diff 回到可解释状态。
settings policy 与组织允许清单把偏好变成可执行控制
个人的 extensions.json recommendation 只是提示,不会阻止未批准扩展,也不能固定版本。VS Code 的企业策略可在受管设备覆盖用户和工作区设置。官方 企业扩展管理文档 给出的能力基线是 VS Code 1.96+:extensions.allowed 可按发布者、完整扩展 ID、指定版本或平台建立允许/阻止规则,受管设备上的 AllowedExtensions 策略会覆盖用户自己填写的设置。除单独的 "*" 总开关外,发布者和扩展 ID 不支持通配符;更具体的完整扩展规则优先于发布者规则。未在清单中的安装被阻断,已安装但后来被禁止的扩展会被禁用,这才接近可证明的准入控制。旧版 VS Code 不具备同等能力,策略 JSON 有重复键或语法错误时整项也可能不生效,因此部署后要检查 Window Log,而不能只看设备管理平台显示“已下发”。
{
"extensions.allowed": {
"*": false,
"publisher.approved-ai": ["1.2.3"],
"publisher.approved-review": "stable"
}
}上例只展示语义:先默认拒绝,再精确放行批准项。实际 JSON 由设备管理策略部署,不应让成员把它当作普通工作区设置自行复制。版本固定需要维护清单;只允许 stable 更易升级但降低可复现性;按发布者放行管理成本低却扩大接受面。选择哪一种取决于数据等级、终端受管程度和升级响应能力。策略语法错误可能导致规则不生效,因此每次部署要在设备上打开 Developer: Policy Diagnostics 与 Window Log,验证被阻断的扩展确实无法安装或被禁用。
组织策略还可控制自动更新、扩展市场、AI/代理能力和遥测设置。它能覆盖受管 VS Code 的设置,但不能替代网络出口、操作系统应用控制、账户撤销和代码审查;更不能约束开发者在另一台未受管设备、网页聊天或独立 CLI 中复制项目内容。私有扩展市场也有单独的产品与账号边界,并不天然证明远端 VS Code Server、VS Code for the Web 或其他兼容编辑器接受同一策略。策略负责减少受管端的误用面,团队还要分别验证本地、SSH/WSL/容器、Codespaces 和 Web 入口。
遥测、资源和长期成本需要和代码质量一起复盘
VS Code 与扩展可能各自发送遥测、崩溃报告、使用统计、认证事件和模型请求。关闭编辑器遥测不必然改变每个扩展的独立数据处理;扩展的隐私声明也不会自动说明模型供应商、代理 server 或远端 host 的所有数据流。先由组织策略确定允许的 telemetry 等级,再对每个 AI 扩展核对它自己的官方隐私与网络说明,并在受控网络中观察实际域名。不要把真实源码、用户标识、token、内部 URL 或完整日志放进遥测诊断附件。
资源成本同样具体:多个 extension host、语言服务器和 AI 索引会占用 CPU、内存、磁盘和网络,远端环境还消耗容器或主机资源。测量时固定代表仓库与 Profile,比较打开项目、空闲、编辑、生成建议、运行测试和禁用后的 code --status;关注趋势而非拿一次机器上的绝对数字做通用标准。若启用扩展后内存持续增长、索引反复重建、网络重试或测试延迟显著增加,先导出日志和 host 状态,再禁用并二分定位。
账号额度、模型调用和网络代理都可能带来预算。团队不需要在仓库中写死价格,而应记录 owner、订阅来源、使用上限、异常阈值、停用责任和审查周期。将“生成更多内容”与“减少缺陷”分开度量:看无关 diff 比例、测试失败率、人工修订量、审查耗时、敏感数据告警和成本异常。高消耗常常源于上下文过宽、扩展重叠或失败重试,不必先扩大权限或购买更多座席。
禁用、卸载与回滚要同时收回行为、凭据和副本
遇到可疑行为、漏洞公告、账户误用或成本异常时,先在 Extensions 视图禁用扩展并 Reload Window,必要时区分仅当前工作区禁用与全局禁用。随后验证聊天命令、补全、Agent、终端集成和网络请求确实停止。禁用能够保留现场以便调查;卸载适合确认不再需要时使用。两者都不会自动撤销 OAuth 授权、删除系统密钥库条目、清空远端 host、移除模型服务账户或删除扩展写出的缓存。
$extensionId = 'publisher.extension' # 使用已确认的唯一 ID
code --disable-extension $extensionId
code --list-extensions --show-versions | Select-String $extensionId
code --uninstall-extension $extensionId
code --list-extensions --show-versions | Select-String $extensionId命令后的预期不是只看 Select-String 没有输出,而是重载窗口后功能入口消失、Running Extensions 不再列出它、远端对应 host 也不存在相同版本、测试仓库没有被再次改写。若扩展是由 Profile 同步或企业预装恢复,卸载后很快重现是有价值的失败证据:说明需要先调整同步、预装或策略,再做本机清理。不要反复手工卸载来掩盖配置源。
回滚升级时先禁用问题版本,恢复上一份批准包或策略允许版本,重启 extension host,然后重复代表项目的打开、只读、编辑、diff、测试和网络验证。最后撤销受影响 token、注销账户、删除不再需要的远端安装、清理脱敏试验数据,并更新扩展台账。真正的退出完成于新 Profile 和新工作区都不会无意恢复该扩展,且审计能解释它何时被引入、谁批准、接触过哪些账户与数据、为何退出。
让每项扩展都有 owner、证据和可拿走的路径
团队基线应保存最少而完整的信息:扩展唯一 ID 与版本、发布者、包来源和签名核验、适用 VS Code 版本、安装位置、本地/远端 host、允许的工作区数据、网络域名、认证方式、Secret Storage 处理、AI/终端/MCP 权限、遥测设置、测试项目、升级节奏、owner、禁用与回滚步骤。它是可查询的工程资产,不是随意增长的推荐列表。
每个版本变化都应在隔离 Profile 上完成一次连贯验证:策略是否允许,扩展是否在预期 host 激活,陌生工作区是否仍受 Restricted Mode 保护,认证是否只使用测试身份,允许的功能是否产生可解释 diff,项目检查和测试是否实际运行,禁用/卸载后是否不留活跃行为。实际执行过的命令、退出码、日志位置和失败证据要单独保存;尚未执行的步骤只作为待执行清单,不能因文档中有命令块就被描述为已验证。
当扩展停止维护、许可或隐私条款发生变化、网络目的地扩大、漏洞超过响应时限、能力与内置功能重复、资源成本无法接受,或 owner 不再存在时,就冻结新安装并开始退出。能安全停用的工具才配进入日常开发:开发者知道它在哪里运行、向哪里发送什么、出了问题怎样停止,审查者也能在不依赖原聊天记录的情况下重放关键判断。
