关于 yof
yof 是面向 AI 应用开发者的命令行安全检查工具,可在本机扫描密钥、可疑依赖和应用访问控制问题。它还可用测试账户攻击自有运行中应用,并将确认的问题转成回归测试;代码不会上传。
主要功能
- 01本地扫描泄露密钥
- 02检查虚构及仿冒依赖
- 03提交前运行暂存区检查
- 04测试自有应用的访问控制
- 05将确认问题生成回归测试
适用场景
- 01提交前发现代码中的密钥
- 02排查新引入的可疑包
- 03验证账户间数据隔离
- 04为已确认问题添加回归测试
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://mcp.yof.io/mcpclaude mcp add --transport http io-yof-yof https://mcp.yof.io/mcp{"mcpServers":{"io-yof-yof":{"type":"http","url":"https://mcp.yof.io/mcp"}}}在 Cursor 中打开{"servers":{"io-yof-yof":{"type":"http","url":"https://mcp.yof.io/mcp"}}}在 VS Code 中打开{"mcpServers":{"io-yof-yof":{"type":"http","url":"https://mcp.yof.io/mcp"}}}{"mcpServers":{"io-yof-yof":{"serverUrl":"https://mcp.yof.io/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
https://mcp.yof.io/mcp需要授权工具
详细介绍
为你用 AI 构建的应用进行安全检查
在发布前发现泄露的密钥、有风险或虚构的包,以及账户之间的访问漏洞。免费且开源。
在发布前发现泄露的密钥和虚构的包。
yof(sōtem 推出的 yof)是运行在你笔记本电脑上的 yof:一个小巧的命令行检查工具,可检查用 AI 助手构建的应用(以及任何其他方式构建的应用)。它能在秘密密钥进入提交、拉取请求或生产环境之前,找出代码中残留的密钥,以及不存在或仿冒热门包的依赖项。
它只使用规则:模式精确、速度快,而且保护隐私。它在你的机器上运行,无需账户,也不会将你的代码发送到任何地方。
30 秒上手
npx @yof/cli check
它会检查当前文件夹。需要 Node 20 或更高版本。无需任何配置。
yof checked 2 files (profile: balanced)
Keys
src/config.ts:1 Stripe live secret key sk_live_FwIw•••••••• (fix now)
A key that was ever committed or shipped counts as leaked: rotate it in the provider's dashboard,
then keep it on the server only (an environment variable, not the code).
Packages
package.json reqeusts-helper (npm) (fix now)
This package doesn't exist on npm. AI assistants sometimes invent package names, and attackers register those names with malware. Check the spelling or remove it.
package.json expres (npm) (fix this week)
This name is one or two letters away from the popular package express. Make sure you meant this one and not express.
Found 3 problems: 2 to fix now, 1 to fix this week.
Want this on every pull request? https://yof.io
yof 不会完整打印密钥。你会看到密钥前缀和末尾四个字符,足以判断它是哪一个密钥。
如果你经常使用,可以安装:
npm install --save-dev @yof/cli
npx yof check
检查每次提交(pre-commit hook)
npx @yof/cli hook install
这会添加 .git/hooks/pre-commit,在每次提交前运行 yof check --staged。在暂存模式下,yof 会读取即将提交的确切内容(已暂存的内容,而不是工作副本),并且只检查此提交新增的依赖项。如果有问题需要立即修复,提交会被阻止,yof 会说明原因。
- 使用
npx @yof/cli hook uninstall将其移除。 - 使用
git commit --no-verify跳过一次。 - 如果你已有 pre-commit hook,yof 会保留原样,并告诉你需要添加哪一行。
检查每次推送(GitHub Action)
# .github/workflows/yof.yml
name: yof
on: [push, pull_request]
permissions:
contents: read
jobs:
yof:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: yof-dev/[email protected]
with:
path: . # optional, default .
offline: false # optional, true = keys only, no registry lookups
如果 yof 发现需要立即修复的问题,任务就会失败,并在提交或拉取请求上显示为红色检查。
设置:.yof.yml
可选。将它放在仓库根目录中。这与 yof Guard 在 GitHub 上读取的文件相同,因此一个文件即可用于两者。
profile: balanced # relaxed | balanced | strict
ignore:
- fixtures/ # a folder
- docs/examples.md # a file
- "**/*.snap" # a glob: * stays inside one folder, ** matches any depth
| 配置档 | 显示 | 在以下情况失败(退出码 1) |
|---|---|---|
relaxed | 立即修复 | 立即修复 |
balanced(默认) | 立即修复,本周内修复 | 立即修复 |
strict | 所有问题,包括无害的公开密钥 | 立即修复,本周内修复 |
命令行中的 --profile strict 会覆盖文件设置。yof 还会跳过 node_modules、.git、dist、build、.next 等类似文件夹、锁文件、二进制文件、大于 1 MB 的文件,以及根目录 .gitignore 中列出的内容(简单来说:普通名称、文件夹和 glob;不会应用 ! 行)。
已接受的风险:.yof/accepted.json
有些发现是有意保留且无害的,例如夹具文件中的已撤销测试密钥。你可以在编辑器中接受某项发现(VS Code:使用快速修复“yof: Accept this risk…”),并填写一句话说明,然后提交它生成的文件:
{ "version": 1, "accepted": [ { "rule": "secret.stripe_test", "file": "tests/pay.ts", "fingerprint": "…", "reason": "A test key in a fixture", "acceptedBy": "Ada", "acceptedAt": "2026-11-07T10:00:00.000Z" } ] }
yof check 仍会在“已接受的风险”下显示已接受的发现,并附上原因、接受人和时间;但它不再将其计为未解决问题,也不会因此导致检查失败。指纹涵盖规则、文件和发现所在行,因此如果该行发生变化,发现就会重新成为未解决问题。删除对应条目即可重新打开它。yof 的签名报告会在“已接受的风险及原因”附录中列出这些条目。
检查内容
密钥(仅匹配确切格式,因此随机哈希不会触发警报):
| 立即修复 | 本周内修复 | 没问题,按设计公开(在严格模式下显示) |
|---|---|---|
| Stripe 实时密钥和受限密钥、Stripe webhook 密钥 | Stripe 测试密钥 | Stripe 可发布密钥 |
| OpenAI、Anthropic、Groq、Hugging Face、Replicate | 单独出现的 AWS 访问密钥 ID | Firebase Web 密钥 |
| AWS 访问密钥及其旁边的密钥 | 类似密钥名称的浏览器可见设置(VITE_、NEXT_PUBLIC_、REACT_APP_、EXPO_PUBLIC_ … SECRET / PASSWORD / PRIVATE) | Supabase anon 密钥 |
| Supabase service-role 密钥(会解码 JWT,而非猜测) | ||
| GitHub 令牌、Slack 令牌和 webhook URL | ||
| Resend、SendGrid、Mailgun、Twilio | ||
私钥(BEGIN … PRIVATE KEY) |
会跳过 sk_live_xxxxxxxx 或 sk_live_your_key_here 之类的占位符,因此文档和示例不会触发警报。
软件包(位于 package.json、requirements*.txt 和 pyproject.toml 中):
- 虚构软件包:该名称在 npm 或 PyPI 上不存在。AI 助手有时会编造软件包名称,而攻击者会注册这些名称并植入恶意软件。(立即修复)
- 相似名称:与热门软件包只差一两个字母(
expres、reqeusts),且本身尚未得到广泛采用。(本周内修复) - 全新软件包:首次发布于过去 14 天内。(本周内修复)
- 已知安全公告:精确固定的版本在 OSV 数据库中有已发布的安全公告。高危和严重问题需要立即修复,其余问题需在本周内修复。
如果软件包注册表没有响应,yof 会说明情况,不会对该软件包妄下结论。
不检查的内容:不会读取 git 历史记录、扫描正在运行的网站、检查数据库规则或审查代码逻辑。这些功能由 yof 应用和 Guard(见下文)提供。
攻击你自己的应用:yof attack
yof attack 会像攻击者一样测试你自己正在运行的应用,使用你为其创建的两个测试账号(A 和 B,以及一个可选的管理员账号)。它只会报告两次测试中都观察到的问题,并将每个问题转化为回归测试。
npx @yof/cli attack http://localhost:3000
npx @yof/cli attack --mode light
它会尝试以下操作:
| 分组 | 操作 |
|---|---|
auth | 在未登录以及使用无效令牌的情况下访问每个需要登录的路由 |
tenant | 账号 A 创建测试记录,账号 B 通过 ID 读取记录、在列表中找到记录并修改记录 |
rbac | 以普通成员身份访问每个管理员路由 |
ai | 测试你自己的助手路由:询问其隐藏指令,在消息中输入命令,在其读取的记录中隐藏命令(HTML 注释、链接标题、“system”字段);询问账号 B 的记录、要求重命名账号 B 的记录以及索取管理员数据;检查账号 B 的记录是否会影响账号 A 的常规回答(RAG 投毒);要求其使用实时 HTML 或图片链接回答、为一个无害词语放弃规则、提供内部地址和工具列表,以及向 .invalid 地址发送电子邮件;仅当设置 "limits": true 时,才会每次发送两条、共发送 10 条简短消息,并要求它讲一个很长的故事 |
surface | 开放重定向、安全标头、登录 Cookie 标志,以及(启用后)连续输入 12 次错误密码 |
安全性由设计保障,并在代码中强制执行:
- 只测试你已证明属于自己的主机。
localhost;GitHub 报告为此仓库针对受测提交成功部署的预览环境;或你通过 yof 应用的验证令牌证明所有权的线上主机(YOF_VERIFY_TOKEN,与 yof 应用使用的文件、meta 标签或 DNS 记录相同)。 - 每个应用都必须提供书面同意,并在配置中逐字写明应用名称。
- 除非配置针对该应用启用了生产环境测试,否则绝不测试生产环境。 启用后,可随时进行轻量测试(只读);完整测试只能在你设置的时间窗口内进行。
- 不发送破坏性请求。 允许 GET 和 HEAD;只有对你指定的创建、登录和助手路由才允许 POST。PATCH、PUT 和 DELETE 只会操作本次运行创建的记录,并且这些记录始终会在运行结束时删除。
- 严格限制预算:默认最多 300 个请求,耗时 110 秒(上限为 2,000 个请求和 15 分钟),请求速率恒定,超时设为 10 秒。预算用尽时,测试会停止并报告原因,然后删除测试记录。
- 随时可以停止。 收到编辑器或 CI 在取消操作时发送的 Ctrl+C(SIGINT)或 SIGTERM 后,不会再发送任何请求;本次运行创建的测试记录会在 10 秒内删除;程序会报告删除了哪些记录以及无法删除哪些记录,并以 130 或 143 退出。再次按 Ctrl+C 会立即退出。
- 助手消息温和且固定。 每次运行使用的助手探测文本都相同(基于 OWASP Top 10 for LLM Applications 2025 中的类别)。没有任何消息要求生成有害内容:越狱探测只要求输出无害的测试词语;图片链接指向
yof-canary.invalid,电子邮件探测使用example.invalid地址,这些地址都无法解析。每个发现都由规则判定,而非模型。对于内部信息,只记录其类型(私有地址、连接字符串、服务器路径、工具列表),绝不记录具体文本。 - 使用量限制需选择启用。 在
ai条目中设置"limits": true,会额外发送 10 条简短消息,并请求生成一个很长的故事,因为这会消耗少量模型用量。不设置时,不会发送此类消息。 - 测试账号信息仅保存在你的 CI 密钥中。 配置中只会指定环境变量,不会包含令牌或密码;yof 不会存储任何信息。
配置文件位于 .yof/attack.json:
{
"app": "shop.example.com",
"consent": "I own shop.example.com and allow yof attack to test it and its preview builds with my own test accounts.",
"accounts": {
"a": { "header": "Authorization", "env": "YOF_ATTACK_A" },
"b": { "header": "Authorization", "env": "YOF_ATTACK_B" },
"admin": { "header": "Authorization", "env": "YOF_ATTACK_ADMIN" }
},
"routes": ["/api/me", "/api/notes"],
"admin": ["/api/admin/users"],
"objects": [{
"create": { "path": "/api/notes", "body": "{\"title\":\"{{marker}}\"}" },
"idPath": "id",
"read": "/api/notes/{id}",
"list": "/api/notes",
"update": { "method": "PATCH", "path": "/api/notes/{id}", "body": "{\"title\":\"{{marker}}\"}" },
"delete": "/api/notes/{id}"
}],
"ai": [{
"path": "/api/chat", "body": "{\"message\":\"{{message}}\"}", "replyPath": "reply",
"ingest": { "create": { "path": "/api/notes", "body": "{\"title\":\"{{document}}\"}" }, "idPath": "id", "delete": "/api/notes/{id}" },
"limits": false
}],
"surface": { "redirectPaths": ["/login"], "rateLimit": false },
"production": { "enabled": false, "window": "02:00-04:00" },
"budget": { "requests": 300, "seconds": 110, "perSecond": 8 }
}
账号也可以使用来自 CI 密钥的电子邮件和密码登录:{ "login": { "path": "/api/login", "body": "{\"email\":\"{{email}}\",\"password\":\"{{password}}\"}", "tokenPath": "token" }, "emailEnv": "YOF_ATTACK_A_EMAIL", "passwordEnv": "YOF_ATTACK_A_PASSWORD" }。如果未设置 tokenPath,则会使用会话 Cookie。
回归测试
使用 --write-tests 时,每个已确认的问题都会在你自己的测试框架中变成一个测试(根据你的仓库检测 Vitest、Jest、Playwright 或 pytest;否则使用 node --test 文件)。它会重放记录的攻击,并验证相反的结果:攻击仍然有效时,测试会失败;修复后,测试会通过。不会由 AI 编写。除非设置了 YOF_ATTACK_TARGET,否则测试会跳过自身,因此不会影响正常的测试运行。
每次拉取请求时
# .github/workflows/yof-attack.yml
name: yof attack
on: [pull_request]
permissions:
contents: read
deployments: read
pull-requests: write
issues: write
jobs:
attack:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: yof-dev/yof/[email protected]
env:
YOF_ATTACK_A: ${{ secrets.YOF_ATTACK_A }}
YOF_ATTACK_B: ${{ secrets.YOF_ATTACK_B }}
YOF_ATTACK_ADMIN: ${{ secrets.YOF_ATTACK_ADMIN }}
它会等待拉取请求的预览部署完成,然后只攻击此次更改可能影响的部分:所更改文件对应的路由(Next.js app 和 pages 路由、Hono 和 Express 路由文件,以及导入了已更改辅助函数的路由)。评论会显示“partial run: N attack groups”。如果更改了共享代码(中间件、身份验证、权限、数据库访问、依赖项),或无法确定映射关系,它就会运行全部攻击组并说明原因。来自复刻仓库的拉取请求会被跳过。
评论会列出发现的问题。在拉取请求中评论 /patch apply,yof GitHub App 就会将回归测试(以及适用时的安全标头修复)提交到该拉取请求自己的分支。此功能仅对拥有写入权限的人员开放,不适用于复刻仓库,也不会作用于默认分支,并且绝不会强制推送。
设置 YOF_HOOK_URL(从 yof 应用获取的部署钩子地址),然后运行 yof attack --upload,即可将经过脱敏的问题发送到 yof 应用,并与其他问题一起显示。
选项
yof attack [url] The address to test (or YOF_ATTACK_TARGET)
--config <file> The attack config (default .yof/attack.json)
--mode <full|light> light = read-only
--base <branch> Pull request run: attack only what the change can reach
--write-tests Write a regression test for every confirmed finding
--comment <file> Write the pull-request comment to this file
--upload Send the masked results to your yof app (YOF_HOOK_URL)
--json Machine-readable output
在你的 AI 构建工具中使用:yof mcp
yof mcp 会将 yof 作为本地 MCP 服务运行(stdio),这样编写代码的 AI 就能在说“完成”之前检查代码。它适用于任何能够启动本地命令的 MCP 客户端。最简单的连接方式是在 yof 控制面板中选择“Connect your AI builder”,它会为你写入配置。也可以手动配置:
claude mcp add yof -- npx -y @yof/cli mcp # Claude Code
codex mcp add yof -- npx -y @yof/cli mcp # Codex CLI
Cursor、VS Code、Windsurf 和 Claude Desktop 在 MCP 设置中使用相同的命令:npx -y @yof/cli mcp。请始终使用带作用域的名称 @yof/cli:不带作用域的 npm 名称 yof 属于其他人。
工具:
| 工具 | 功能 | 运行位置 |
|---|---|---|
yof_check | 扫描项目文件夹(或其中的文件夹) | 你的设备 |
yof_check_diff | 仅扫描已更改的行(你传入的差异,或工作树与上次提交之间的差异,以及新文件) | 你的设备 |
yof_explain | 说明规则的含义、重要性及安全的修复方式 | 你的设备 |
yof_fix_prompt | 针对某个问题提供精确的修复步骤 | 你的设备 |
yof_verify | 重新扫描某个文件,并说明是否已修复 | 你的设备 |
yof_findings | 查看 yof.io 账户中的未处理问题 | yof.io,需要 YOF_API_KEY |
yof_patch_status | 查看 Patch 的未合并拉取请求及其 CI 状态 | yof.io,需要 YOF_API_KEY |
yof_lessons | 查看已合并 Patch 修复的备注 | yof.io,需要 YOF_API_KEY |
每条答复都会以一行文字开头,声明其内容是来自已扫描项目的不可信数据,因此文件中的文本绝不会被当作指令读取。机密值始终以短前缀加 REDACTED 的形式返回。限制:差异最多为 1 MB、300 个文件;扫描会在 90 秒后停止;路径必须位于项目文件夹内。
YOF_API_KEY 由 yof 控制面板为单个连接生成,你可以随时在控制面板中撤销。设置该密钥后,服务启动时会发送一次 ping(以便控制面板显示连接是否正常);对于三个账户工具,服务还会发送工具名称及其参数(ID 和规则 ID)。绝不会发送代码或文件内容。
隐私
yof check 在你的计算机上运行。它会读取文件、匹配模式并打印结果。你的代码、文件名和密钥绝不会离开你的计算机。(yof attack 只会向你证明属于自己的应用发送请求,并调用 GitHub 的 API 读取此仓库的部署信息。)
yof check 唯一的网络请求是查询软件包注册表:软件包名称(以及精确固定的版本)会发送至 registry.npmjs.org、api.npmjs.org、pypi.org 和 api.osv.dev,不会发送至其他主机。使用 --offline 可跳过这些查询,此时 yof 完全不会发起网络请求。没有遥测。
选项
yof check [path] Check a folder (default: the current one)
yof check --staged Check only the files staged for the next commit
yof hook install Run "yof check --staged" before every commit
yof hook uninstall Remove that hook
yof diff Check only what changed since the last commit (plus new files)
yof mcp [path] Run yof as a local MCP server for AI builders
yof import <file> [path] Read a findings.json and check each record's file and line here
--offline Skip the package-registry lookups (keys only)
--json Machine-readable output (masked values only)
--format <name> text | json | findings-json
--profile <name> relaxed | balanced | strict
-v, --version Print the version
-h, --help Print help
退出代码:0 表示无需修复,1 表示有需要修复的问题(根据配置文件判断),2 表示用法或设置错误。
使用 --json 时,每条发现还会包含 why(用通俗语言说明可能发生什么)和 fixPrompt(说明要更改什么,可直接粘贴给编写该代码的 AI 助手,其中只包含经过遮蔽的值)。yof 的编辑器插件会直接显示这些内容。
findings.json(Cloudflare 的安全审计格式)
yof check --format findings-json 会以 Cloudflare 安全审计技能的 findings.json 格式写入发现(采用 MIT 许可证,见 NOTICE),因此能够读取该格式的工具也能读取 yof 的结果。每条记录都带有一个判定结果:如果文件夹中存在确切证据(符合服务商格式的密钥、注册表中不存在的软件包,或公告列出的已安装版本),则为 confirmed;如果只是很可能存在,但尚未证实(名称与热门软件包相差一两个字母,或仅发布几天的软件包),则为 needs_validation。按设计公开的密钥属于加固提示,不算作发现,因此不会列出。yof check 发现的问题不会被评为严重:它不会运行你的代码,也不会访问在线应用,因此最高评级为“高”。
yof import findings.json [path] 会严格读取 findings.json(如果某条记录包含未知字段、缺少字段、值错误,或严重性超过其已证实的影响,就会指出该记录并将其排除,不会修正),并以只读方式对照文件夹检查每条记录:文件是否存在于文件夹内,以及对应行是否存在。不会运行任何内容,也不会发送任何内容。如果文件不符合架构,则退出代码为 2;如果有记录需要检查,则为 1;如果只剩下被排除的记录,则为 0。
你也可以将其用作库:import { scanText, checkPackages, runCheck } from "@yof/cli"。
想了解更多?
yof 是面向 AI 构建应用的安全监控工具。这个 CLI 是其中快速、私密、基于规则的部分。其他功能请访问 yof.io:
- yof 应用位于 yof.io,可监控在线应用,用通俗语言解释每条发现、说明如何修复,并持续跟踪应用的变化。
- Guard 会审核 GitHub 上的每个拉取请求,并留下简明的评论:github.com/apps/yof-by-sotem。
- Patch 是 yof 的 AI Agent,会为你编写修复内容,并以草稿拉取请求的形式提交。
参与贡献
欢迎提交问题和拉取请求,尤其欢迎带有明确格式说明的新密钥规则。请参阅 CONTRIBUTING.md。安全问题请参阅 SECURITY.md。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。