LLM Agent Skills凭据泄露风险分析:从机制到防护实践
2026/8/31 17:52:48 网站建设 项目流程

LLM Agent Skills 正在成为 Agent 应用里复用能力的主要方式,但随之而来的凭据(Credentials)泄露风险往往被开发者低估。一篇题为《Credentials Are Leaked by LLM Agent Skills: An Empirical Study》的研究把这个问题摆到台面上:API Key、数据库口令、云厂商访问密钥、OAuth Token,都有可能在 Skill 的输出、日志、错误信息或仓库文件中被意外暴露。下面这篇文章会结合 Agent Skills 的运行机制,先解释凭据为什么容易在这里泄露,再提供一个可本地复现的最小实验,最后给出检测、排查和生产环境落地的防护建议。无论你是 Agent 应用开发者、LLM 框架使用者,还是负责平台安全的技术人员,都可以按这套方法梳理自己项目里的风险面。

需要先说明一点:这篇文章不引用原论文的具体实验数据和结论,只围绕“Credentials Are Leaked by LLM Agent Skills”这个事实方向,搭建一套可自行验证的安全分析框架。所有实验都使用伪凭据,不连接真实服务,也不依赖外部模型厂商。

1. Agent Skills 的凭据风险要从机制说起

1.1 从“工具”到“技能”,安全边界发生了转移

在传统 Function Calling 或者插件模型里,开发者会为模型注册一组函数:

{ "name": "query_order", "description": "查询订单信息", "parameters": { "type": "object", "properties": { "order_id": {"type": "string"} }, "required": ["order_id"] } }

函数本身只是描述,真正的业务逻辑由后端服务执行,执行结果是否返回给模型、返回哪些字段,还可以在代码里做二次控制。Agent Skills 则更进一步。一个 Skill 更像是一个可以独立执行的小任务单元,通常由三部分组成:

  1. 一份描述文件,比如skill.yaml,说明这个 Skill 是干什么的、需要哪些环境变量、执行什么命令;
  2. 一段可执行脚本或命令,比如 Python、Shell;
  3. 一个输出结果,执行后的 stdout、stderr 或者返回 JSON 会被组装回 Agent 的上下文。

这种设计让模型可以“看懂”技能并动态决定是否调用,但安全边界也随之转移。普通脚本是开发者写死调用链路的,输出数据不会自动进入模型上下文;而 Agent Skill 的调用决策交给模型,执行产生的原始输出又常常原样拼进上下文。两边叠加,凭据暴露的窗口比静态脚本大很多。

下表整理了几个关键差异。

对比维度传统 Function CallingAgent Skills
能力载体函数、后端接口脚本、命令、描述文件
谁决定调用开发者编排或模型按 schema 调用模型根据 description 自主选择
输出流向可以结构化过滤往往是文本回传,容易被透传
凭据管理位置集中在后端服务分散在 Skill 目录、配置和环境变量里
风险特征边界清晰,容易收敛边界分散,需要额外脱敏处理

1.2 一次 Skill 调用的完整生命周期与凭据接触点

要理解凭什么据会泄露,先看一个 Agent Skill 从定义到执行的完整过程:

  1. 开发者编写 Skill 目录,包含描述文件和执行脚本;
  2. 将 Skill 注册到 Agent 编排框架;
  3. Agent 运行时加载 Skill 元数据,把描述和参数说明提供给模型;
  4. 模型根据用户请求选择某个 Skill;
  5. 框架执行 Skill 的 command,捕获 stdout 和 stderr;
  6. 执行结果被写入 Agent 对话上下文;
  7. 日志系统记录本次调用的元数据、入参和输出。

凭据在这个流程里有几个潜在接触点:

  • 第 1 步:如果凭据写在脚本、.envskill.yaml里,源码和配置就是泄露源;
  • 第 5 步:脚本在调试日志或 stdout 里打印环境变量,凭据会进入执行输出;
  • 第 6 步:输出中包含的连接串、Token 会进入模型上下文,控制权离开应用层;
  • 第 7 步:中心化日志保存了完整 stdout,变成第二个存储侧泄露点。

这里最容易误解的是“只要凭据放在环境变量里就安全”。实际上,环境变量只是不把秘密写死在源码里,但如果程序在日志中打印os.environ、debug 时输出DB_PASSWORD,或者异常信息里包含完整配置对象,凭据依然会从输出通道泄露出去。

1.3 和 n8n、Flowise 等编排平台的 credentials 差异

在 n8n、Flowise 这类工作流平台中,Credentials 通常有独立配置页,用户把 API Key、Token 存到平台的凭据仓库,节点只引用变量名。这种模式相对集中,风险主要集中在平台本身的鉴权和存储。

Agent Skills 不同。当前很多实现是“落盘”的:一个 Skill 就是一个目录,里面除了描述文件,还有脚本、配置,甚至.env。如果采用同样松散的凭据管理方式,每个 Skill 目录都可能成为独立泄露源。这也是实证研究值得关注的原因:当 Skill 数量多起来,凭据不是集中在一个地方,而是散落在几十上百个目录里,检测和治理难度会显著上升。

2. 凭据泄露的四种典型链路

2.1 写入侧:配置、源码和 .env 进入版本库

最常见的一类泄露发生在代码被写下来的一瞬间。Skill 的目录天然是“自包含”的,开发者为了方便,会在脚本里硬编码密钥,或者把DB_PASSWORD写进skill.yaml,再或者在 Skill 目录下放一个.env

这类问题在普通项目里也有,但 Skill 让问题更容易出现,因为 Skill 的复制传播成本很低:一个写好了数据库凭据的 Skill 可能被团队成员直接复制到另一个项目里,而.gitignore未必覆盖每个 Skill 目录。

还有一种情况是环境变量文件没有被忽略,或者被 CI 过程作为产物上传。此时凭据不仅进入源码仓库,还可能进入构建日志、镜像层、制品仓库。后续清理成本非常高。

2.2 执行侧:debug 日志、stdout 和进程信息

Agent 框架执行 Skill 时,通常会用子进程方式运行命令并捕获输出。看一个常见实现:

import subprocess def run_skill(command: str): output = subprocess.check_output( command, shell=True, text=True, stderr=subprocess.STDOUT ) return output

这个代码本身没有把凭据写进日志,但只要 Skill 脚本中写了类似:

logging.debug("connect db user=%s password=%s", user, password)

那么password就会通过 stderr 被 subprocess 捕获。再由框架把这个输出组织成结果交给模型,甚至写入日志。

shell=True还会带来另一条泄露路径:当命令字符串包含动态拼接的参数时,整个命令行可能出现在操作系统的进程列表或者 shell 历史里。如果拼接内容里有 Token,凭据就等于落到了进程监控工具和管理员日志里。

2.3 模型侧:输出作为模型上下文,边界不可控

Agent Skill 的价值在于模型能理解执行结果并决定下一步动作。因此框架往往会尽量把 Skill 的 stdout 完整传给模型,而不是只传一个状态码。

问题就在这里。如果脚本返回了这样的结果:

{ "status": "success", "connection": { "host": "127.0.0.1", "user": "demo_user", "password": "FakePass123!" } }

这段文本会进入模型上下文。一旦进入模型服务方或者中转链路,应用所在方就失去了对这部分数据的完全控制。即使模型不会主动输出这个字段,数据也已经越过应用边界,进入了第三方可观测范围。这是 Agent Skills 特有的风险,因为普通函数调用通常可以设计“只返回必需字段”,而 Skill 输出往往是原始文本。

这里要强调一点:不要把希望寄托在“模型不会乱说”上。安全边界应该设计在输出形成之前,而不是依赖模型对数据的自动隐藏。

2.4 异常侧:堆栈和回退信息包含连接串

很多开发者在异常处理里习惯“把完整错误信息返回给模型,让模型继续尝试”。例如:

except Exception as exc: return f"执行失败,完整错误:{str(exc)}"

如果str(exc)里包含数据库连接字符串、配置对象、环境变量字典,异常消息就会带走凭据。

例如配置对象转字符串后可能是这样:

Config(host=127.0.0.1, user=demo_user, password=FakePass123!, database=demo_db)

这类内容进入模型上下文后,日志和追踪系统也会同步记录。异常回退是一个非常隐蔽的通道,因为它不是业务输出,只在任务失败时出现,但恰恰最容易携带调试信息。

2.5 泄露链路横向对比

泄露链路发生阶段典型凭据主要通道
源码写入Skill 开发时硬编码密钥、.env版本库、镜像、制品
执行输出脚本运行时密码、Token、连接串stdout、stderr、进程列表
模型上下文结果回传脱敏缺失的返回体LLM 请求内容
异常回退任务失败时配置对象、异常堆栈错误消息、日志

3. 复现研究思路:搭一个最小可运行的凭据泄露实验

原论文的研究方式是实证分析,那我们也用实验思路来建立直觉。下面这个实验不连真实数据库、不调用真实模型,只模拟“Agent Runner 执行 Skill 并捕获输出”这个过程。所有密码、Token 都是伪凭据,即使泄露也不影响任何真实服务。

3.1 实验目标、安全边界和环境准备

实验目标有三个:

  1. 观察坏写的 Skill 如何把凭据带到 stdout;
  2. 观察 debug 日志如何把凭据带进 stderr;
  3. 用一个静态扫描脚本,找出这些疑似凭据点。

环境要求很低:

项目要求说明
Python3.9 及以上仅使用标准库
操作系统Linux / macOS / Windows示例命令以 Linux 风格展示
外部依赖不需要安装第三方包
真实凭据不使用全部使用占位值

建议准备一个独立目录agent-skills-security-lab,实验结束可以直接删除。不要把这个实验放在真实项目的上层目录里运行,避免扫描出真实环境的敏感信息后误处理。

3.2 准备三个 Skill 样本

目录结构如下:

agent-skills-security-lab/ ├── detector.py ├── runner.py ├── skills/ │ ├── .env.example │ ├── bad_hardcode/ │ │ ├── skill.yaml │ │ └── run.py │ ├── debug_output/ │ │ ├── skill.yaml │ │ └── run.py │ └── safe_skill/ │ ├── skill.yaml │ └── run.py

先看坏示例一:把密码放进返回结果里。

# skills/bad_hardcode/run.py import json # 错误示范:为了说明问题,把凭据以调试字段带出 DB_PASSWORD = "FakePass123!" DB_USER = "demo_user" host = "127.0.0.1" result = { "status": "success", "connection": { "host": host, "user": DB_USER, "password": DB_PASSWORD } } print(json.dumps(result, ensure_ascii=False))

它的技能描述文件:

# skills/bad_hardcode/skill.yaml name: bad_hardcode description: 查询演示数据库订单数量 type: command command: python run.py env: - DB_HOST - DB_USER - DB_PASSWORD

坏示例二:debug 日志输出环境变量。

# skills/debug_output/run.py import os import logging logging.basicConfig(level=logging.DEBUG) DB_USER = os.getenv("DB_USER", "demo_user") DB_PASSWORD = os.getenv("DB_PASSWORD", "fallback_secret") # 错误示范:debug 日志直接记录完整环境变量 logging.debug("开始连接数据库 user=%s password=%s", DB_USER, DB_PASSWORD) print("查询完成")

安全示例:不打印凭据,只输出业务状态和会话信息。

# skills/safe_skill/run.py import os import logging logging.basicConfig(level=logging.INFO) DB_USER = os.getenv("DB_USER", "") # 演示从外部临时凭据源获取,不在脚本里硬编码 token = os.getenv("DB_TOKEN", "") # 记录时只保留脱敏信息,不打印完整 token safe_token = token[:4] + "****" if token else "N/A" logging.info("connect db=demo_orders user=%s token=%s", DB_USER, safe_token) print("query_ok")

再放一个常见的.env.example,演示“配置文件即使只是模板,也可能被扫描器识别”。

# skills/.env.example DB_HOST=127.0.0.1 DB_USER=demo_user DB_PASSWORD=change_me

这里的关键点是:safe_skill仍然打印了token=abcd****,但只保留前 4 位,并且整体是脱敏格式。实际生产里还可以更保守,比如日志里只打印session_id,完全不出现 token 前缀。

3.3 用 Runner 模拟 Agent 调度过程

下面写一个简化版 Runner,遍历skills目录下的每个 Skill,执行skill.yaml里声明的命令,捕获 stdout 和 stderr。它模拟的是主流 Agent 框架“执行 Skill -> 收集输出 -> 返回给模型”的核心链路。

# runner.py import os import subprocess from pathlib import Path BASE_DIR = Path(__file__).parent SKILLS_DIR = BASE_DIR / "skills" def run_skill(skill_dir: Path) -> str: # 演示场景固定执行 python run.py # 真实项目应该解析 skill.yaml 中的 command 字段 command = "python run.py" try: output = subprocess.check_output( command, cwd=skill_dir, shell=True, text=True, stderr=subprocess.STDOUT, ) return f"[stdout]\n{output}" except subprocess.CalledProcessError as exc: return f"[failed]\n{exc.output}" def main(): for skill_dir in sorted(SKILLS_DIR.iterdir()): if not skill_dir.is_dir(): continue if not (skill_dir / "skill.yaml").exists(): continue print(f"==== Skill: {skill_dir.name} ====") print(run_skill(skill_dir)) print() if __name__ == "__main__": main()

这里用shell=True是为了模拟很多真实项目里的写法和风险。生产环境不建议这样做,尤其是当 command 字符串包含外部输入或环境变量时,应当改用参数列表方式调用,避免命令注入和进程列表泄露。

3.4 运行实验,查看泄露现象

在项目根目录执行:

cd agent-skills-security-lab python runner.py

预期输出如下:

==== Skill: bad_hardcode ==== [stdout] {"status": "success", "connection": {"host": "127.0.0.1", "user": "demo_user", "password": "FakePass123!"}} ==== Skill: debug_output ==== [stdout] DEBUG:root:开始连接数据库 user=demo_user password=fallback_secret 查询完成 ==== Skill: safe_skill ==== [stdout] INFO:root:connect db=demo_orders user=demo_user token=N/A query_ok

可以看到前两个 Skill 都出现了明显的凭据泄露:

  • bad_hardcodepassword放进了返回 JSON;
  • debug_outputpassword打印到了日志输出;
  • safe_skill只暴露了脱敏后的 token 前缀,风险可控。

如果这个实验接入真实模型,bad_hardcodedebug_output的整段输出都会进入模型上下文。即使模型本身不记录这些内容,凭据也已经通过了应用层边界。

3.5 用 detector.py 做静态扫描

静态扫描不能替代人工审计,但可以快速发现已知模式。下面写一个启发式扫描器,识别passwordapi_keysecrettoken、云访问密钥和私钥片段。

# detector.py import re import sys from pathlib import Path SECRET_PATTERNS = [ (re.compile(r"(?i)(password|passwd|pwd)\s*[:=]\s*\S+"), "password"), (re.compile(r"(?i)(api[_-]?key|secret|token)\s*[:=]\s*\S+"), "api key/secret/token"), (re.compile(r"(?i)(AKIA[0-9A-Z]{16})"), "cloud access key sample"), (re.compile(r"(?i)(BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY)"), "private key"), ] EXCLUDE = {".git", "__pycache__", ".venv", "node_modules"} def scan_file(path: Path): findings = [] try: text = path.read_text(encoding="utf-8", errors="ignore") except Exception: return findings for lineno, line in enumerate(text.splitlines(), 1): for pattern, name in SECRET_PATTERNS: if pattern.search(line): findings.append((lineno, name, line.strip())) return findings def main(root: Path): total = 0 for path in root.rglob("*"): if path.is_dir(): continue if any(part in EXCLUDE for part in path.parts): continue if path.suffix == ".pyc": continue findings = scan_file(path) for lineno, name, line in findings: total += 1 print(f"{path}:{lineno} [{name}]") print(f" -> {line[:160]}") print(f"\n扫描完成,共发现 {total} 处疑似凭据点。") if __name__ == "__main__": main(Path(sys.argv[1]) if len(sys.argv) > 1 else Path(__file__).parent)

执行扫描:

python detector.py .

预期输出类似:

skills/.env.example:3 [password] -> DB_PASSWORD=change_me skills/bad_hardcode/run.py:9 [password] -> result = {"status": "success", "connection": {"host": host, "user": DB_USER, "password": DB_PASSWORD}} skills/debug_output/run.py:10 [password] -> logging.debug("开始连接数据库 user=%s password=%s", DB_USER, DB_PASSWORD) 扫描完成,共发现 3 处疑似凭据点。

从这个结果能看出两个重要事实:

  1. 静态扫描可以发现源码和配置里的凭据点,但未必能发现运行期动态拼出的凭据;
  2. 即使扫描到password,也需要人工判断是真实泄露还是字符串字面量误报。

所以扫描是第一步,运行期检测和日志审查才是完整闭环。

注意:实验中的所有伪凭据只用于本地演示。不要把.env.exampleFakePass123!change_me直接当成安全示例复制到生产项目。

4. 输出侧排查:在凭据进入模型上下文之前拦下来

4.1 先判断泄露发生在哪一个接触点

拿到一份泄露报告时,不要急着改日志,先判断泄露点:

泄露现象大概率发生位置排查方向
Git 历史里有密码写入侧.gitignore、历史提交、镜像层
运行时 stdout 有 Token执行侧查脚本 print、json dumps、调试输出
日志系统出现凭据日志侧查 logging 配置、日志采集管道
模型输出里出现凭据上下文侧查传给模型的完整结果、异常消息
进程列表出现 Token命令执行侧shell=True、字符串拼接命令

排查顺序建议是:先看输出,再看日志,再查源码写入,最后检查模型上下文。输出不泄露,日志通常也不存在;源码和配置是源头,必须同时收敛。

4.2 输出侧拦截:设计统一的脱敏层

Agent 框架里比较有效的做法是,在“Skill 输出”进入模型上下文之前加一层统一脱敏函数。它的职责是扫描所有要回传给模型的文本,把高风险字段替换成掩码。

import re # 统一脱敏规则:匹配常见凭据字段 REDACT_PATTERNS = [ re.compile(r"(?i)(password|passwd|pwd)\s*[:=]\s*\S+"), re.compile(r"(?i)(token|api[_-]?key|secret)\s*[:=]\s*\S+"), re.compile(r"(?i)(Bearer\s+)[A-Za-z0-9._~+/-]+=*"), ] def redact_output(text: str) -> str: result = text for pattern in REDACT_PATTERNS: result = pattern.sub(r"\1***", result) return result

使用时机很关键:脱敏层不能放在 Skill 脚本内部,因为每个 Skills 写法都不一样;应该放在框架层,作为所有 Skill 输出的统一出口。这样即使某个 Skill 写得不规范,框架也能兜底。

脱敏层也会带来副作用:内容被掩码后,模型可能无法基于真实字段继续完成任务。因此更合理的做法是先在 Skill 规范里约定“任何凭据字段不得出现在返回值中”,脱敏层只是最后一道防线。

4.3 日志与追踪链路排查

日志系统是凭据的第二个“记忆仓库”。即使 stdout 没有泄露,只要日志采集器把 stderr 和完整堆栈写入 Elasticsearch、Loki 或云日志服务,凭据就会长期保存。

排查日志链路时重点看三处:

  1. logging.basicConfig(level=logging.DEBUG):项目里是否存在过宽的日志级别;
  2. 是否把os.environ、配置对象、异常对象直接str()后写入日志;
  3. 日志采集器是否自动记录环境变量或 HTTP Header。

如果使用的是开源日志协议,比如 OpenTelemetry,要关注 Span Attribute 里是否填充了敏感字段。很多默认采集不会自动脱敏,需要显式配置密钥过滤规则。

4.4 常见坑与处理建议

常见坑为什么危险处理建议
.env文件被提交到 Git凭据进入版本历史和分发渠道删除历史、轮换凭据、完善.gitignore
debug 日志打印os.environ环境变量字典包含全部密钥只打印变量名,不打印值
Skill 返回 JSON 带调试字段输出会直接进入模型上下文返回前白名单过滤字段
异常处理返回str(exc)连接串、配置对象可能被包含返回错误码和摘要,屏蔽敏感字段
shell=True拼接命令行命令字符串进进程列表和 shell 历史使用参数列表方式调用
集中式日志未脱敏凭据被持久化保存日志采集前做掩码处理

5. 生产环境防护落地

5.1 凭据注入方式:从“跟随 Skill”改为“运行期注入”

最核心的迁移目标,是让 Skill 目录里不出现任何凭据。Skill 打包、分发、复制时,目录里只有代码和描述文件,没有.env,没有硬编码密钥。

运行期注入的方案可以按项目复杂度选择:

方案适用场景优点注意点
进程环境变量小型项目简单直接不许打印,不许写日志
密钥管理服务中大型项目集中存储、审计需要网络权限和 SDK
OIDC 短期凭据云原生容器或 CI无长期密钥,自动轮换需要平台支持和角色配置

如果暂时无法迁移到密钥管理服务,也应该立即执行两条规则:Skill 目录不允许存在.env文件;所有脚本只允许从外部注入的环境变量读取密钥,不允许在代码里写默认密钥。

5.2 最小权限和短期凭据

给每个 Skill 分配独立身份,而不是让所有 Skill 共用一个高权限账号。独立身份的意义在于:一个 Skill 泄露凭据,只影响它对应的函数、表和 API 范围,不会波及其他能力。

配合短期凭据使用效果更好。例如数据库可以使用临时密码,云资源可以用 OIDC 换取短期 Token。短期凭据过期后即使进入日志,价值也会大大降低。

5.3 生命周期治理:写前扫描、运行监控、日志脱敏

凭据治理应该是持续过程,而不是上线前的一次性检查:

  1. 写代码阶段:IDE 插件或 pre-commit 钩子扫描新增代码;
  2. 提交阶段:CI 里跑 gitleaks、trufflehog 等工具;
  3. 运行阶段:框架层统一脱敏输出;
  4. 日志阶段:日志采集后执行敏感字段过滤和告警;
  5. 响应阶段:发现泄露后立即轮换凭据,并调查泄露范围。

考虑到工具版本和项目环境的差异,这里不展开某个工具的安装步骤,落地前要以当前项目使用的版本和文档为准。核心思路是“每一层都设一道闸门”,不能只靠开发者自觉。

5.4 学习环境、测试环境、生产环境差异

维度学习环境测试环境生产环境
凭据来源可写死或使用占位值独立测试库,最小权限密钥管理服务或短期 Token
日志级别DEBUG 可开INFO/WARN,脱敏后查强制脱敏,禁止打印凭据
模型调用可控沙箱,使用伪数据严格限制返回内容统一脱敏层兜底
泄露响应删除实验目录即可轮换测试凭据事件响应,撤回历史,通知相关方

注意:不要用生产凭据在测试环境里跑实验。测试环境一旦接入真实密钥,泄露影响并不比生产环境小多少。

6. 团队可复用清单与后续方向

6.1 上线前检查清单

每次发布一个 Agent Skill 前,至少检查以下项目:

  1. Skill 目录里是否存在.env、密钥文件、证书、.pem
  2. skill.yaml中是否有passwordtokenapi_key字段;
  3. 运行脚本是否把环境变量或配置对象输出到日志;
  4. 异常处理是否会把完整堆栈返回给模型;
  5. 框架层是否有输出脱敏函数;
  6. 日志采集系统是否配置了敏感字段过滤;
  7. 该 Skill 使用的凭据是否对应最小权限账号;
  8. 凭据是否设置了过期时间;
  9. 是否能在中心化日志系统里搜索到该 Skill 名称,并确认没有敏感数据;
  10. 是否把实验目录排除在扫描范围之外。

6.2 泄露事件的响应路径

如果已经确认凭据泄露,按以下顺序处理:

  1. 立即吊销或轮换泄露的凭据;
  2. 确认泄露范围:源码仓库、日志系统、镜像、模型上下文、第三方服务;
  3. 检查泄露凭据的权限范围,判断是否还需要撤销相关账号权限;
  4. 定位泄露源头,修复写入或输出代码;
  5. 增加自动检测规则,避免同类问题再次出现;
  6. 保留审计记录,确认是否有异常访问。

不要等到“定位到根因再轮换密钥”。凭据一旦进入模型上下文或日志系统,就无法确认谁看到过,第一时间轮换是止损的前提。

6.3 如何持续验证防护效果

持续验证不能只靠代码 review,建议周期性执行三件事:

  1. 随机抽取部分 Skill,运行实验脚本并抓取 stdout、stderr、返回给模型的文本,检查是否出现占位密文;
  2. 在测试环境用一组“伪泄露样例”验证检测规则是否有效;
  3. 定期扫描 Git 历史,确认历史提交中不会重新出现凭据。

如果团队引入了观测系统,还可以关注三类指标:隐藏凭据检测命中数、日志脱敏覆盖率、密钥轮换频率。检测命中数快速下降不一定代表绝对安全,但持续为零且覆盖范围明确,至少说明基础面被控制住了。

Agent Skills 给自动化和 LLM 应用带来了很灵活的封装方式,但这份自由也意味着输出不能被当作可信数据直接消费。凭据泄露并不是单个开发者编码习惯差造成的,而是 Skill 这种封装单元天然把命令、配置和输出绑在了一起。设计阶段就让 Skill 不持有凭据,运行时从外部获取最小权限的短期身份,输出前用统一脱敏层拦截,存储侧坚持扫描仓库、日志和 CI,Agent 的自动化程度越高,凭据反而应该越安全。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询