首页
/ LobeHub deep-review 安全维度:注入、越权与泄密审查规则全解析

LobeHub deep-review 安全维度:注入、越权与泄密审查规则全解析

2026-09-04 16:00:33作者:范靓好Udolf

本篇以 LobeHub 仓库中 deep-review 技能的安全维度规则文件 security.md 为主体,逐条拆解其检查清单、违规判定与豁免机制,并结合仓库中的真实防御实现(如 packages/ssrf-safe-fetch)说明每条规则背后对应的代码事实。读完你能掌握:如何在 LobeHub 这类「Next.js + TRPC + Drizzle」的多端架构中,对一次 diff 做注入、授权绕过与敏感信息泄漏三类安全审查,以及为什么安全维度在整个评审体系里享有"不受代码库惯例校准约束"的特殊地位。

1. 安全维度在 deep-review 技能中的定位

deep-review 是 LobeHub 仓库内置的多维度代码评审技能(SKILL.md),每个评审维度对应 references/dimensions/ 下的一份独立规则文件,light 模式只读该文件的 Quick checklist,deep 模式则要求评审子代理通读全文件并跟随其路由表读取规则来源。安全维度在技能维度表中的登记如下:

  • id 前缀为 sec,即该维度产出的每条发现(finding)编号形如 sec-1sec-2
  • 覆盖范围为 "injection, auth bypass, secret/PII leakage, business-slot confidentiality";
  • Verified? 一列为 yes,意味着它的安全发现必须经过独立的 verify 子代理逐条证伪,而不是直接进报告。

仓库根的 AGENTS.md 在 "Code Review" 一节明确要求:评审 PR / diff / 分支前必须先读 deep-review 技能,普通评审请求走 light 模式(一个独立评审者对照各维度 Quick checklist),完整多子代理 deep 模式仅在显式调用时运行。这正是本文规则文件的生效入口。

1.1 关键设计:安全维度豁免"代码库校准"

deep-review 的核心原则第 4 条是"按代码库现状校准"——如果某种写法在存量代码中普遍存在、且本次 diff 没有使其恶化,就不算发现。但 SKILL.md 在同一原则末尾特别标注:(Security is exempt from all calibration — see the dimension file.) 安全维度被整体豁免。

这条豁免在两处模板中落地:

  • 评审子代理提示词 review-prompt.md 的 Calibration 小节写明:维度文件可声明 calibration_exempt: true(例如 security),声明后"无论是否有先例都要上报"(report regardless of precedent);
  • 验证子代理提示词 verify-prompt.md 的第 9 步要求对"代码库与生命周期校准"逐条应用,但"除非维度声明了 calibration_exempt: true"——也就是说,验证环节也不能以"别处早就这么写了"为由把安全问题判为误报。

对应地,安全维度文件自身的 frontmatter 就声明了这一点:

---
id_prefix: sec
verify: true
skip_when: lockfile/generated-only diff (docs, i18n copy, comments are leak vectors  never skip for text changes)
calibration_exempt: true
---

其正文开宗明义:"This dimension is exempt from the codebase-calibration principle: a vulnerability is a finding even if the same weakness exists elsewhere in the repo, and severity is never downgraded for precedent."(漏洞就是发现,即使同样的弱点在仓库别处已经存在;严重性永不因先例而降级。)这与 SKILL.md 维度表中 security 行 Verified? = yes 的设定互为表里——安全发现既独立于先例,又必须经过独立验证。

1.2 什么时候可以跳过安全维度:pruning 表的唯一豁免条件

SKILL.md 的裁剪表(Pruning table)规定了每个维度的跳过条件,security 一行是:仅在 lockfile/generated-only diff 时跳过;而文档、i18n 文案变更仍然要跑安全维度——因为"文本本身就是泄漏向量:密钥、内部 URL、商业细节"。frontmatter 里的 skip_when 字段(docs, i18n copy, comments are leak vectors — never skip for text changes)是这一规则在维度文件内的镜像。

这个设计针对的是 LobeHub 这类 i18n 密集型仓库的现实风险:18 个语言目录(locales/ar/locales/zh-TW/,每个含 50+ 命名空间 JSON 文件)中的文案改动,完全可能把 API 密钥、内网地址或商业逻辑细节写进提交历史。

2. Quick checklist:八条注入/授权/泄漏检查项逐条解析

Quick checklist 是 light 模式评审者必须完整读取的部分(含嵌套示例小节),也是 deep 模式的骨架。原文共八条,这里逐条展开其在本仓库技术栈下的具体含义。仓库的技术底座(见 AGENTS.md "Tech Stack")是 Next.js 16 + React 19 + TypeScript、TRPC 类型安全后端、Drizzle ORM + PostgreSQL、SWR 数据获取——这决定了每条检查项的实际落点。

2.1 注入(Injection)

user input reaching SQL (raw sql fragments), shell commands, dangerouslySetInnerHTML, path construction

本仓库数据访问层是 Drizzle ORM(packages/database/),常规查询走参数化;检查项特意点名原始 sql 模板片段,因为 Drizzle 允许 sql 模板标签拼接用户输入,一旦未参数化即成 SQL 注入面。另外三类 sink 分别是:shell 命令拼接(后端 apps/server/ 与 Electron 桌面端 apps/desktop/ 都存在进程与脚本调用场景)、React 的 dangerouslySetInnerHTML(富文本渲染路径)、以及路径构造(文件上传、知识库文件加载等会拼接磁盘路径)。

2.2 授权(Authorization):以"邻居实现"为标尺

new TRPC procedures / API routes missing the auth middleware their siblings use; queries missing user-scoping (userId filter) that sibling queries apply

这条规则的执行方法写死在"How to check"第 2 步:打开同一 router 下两个相邻的 procedure,对比它们的中件件与用户范围过滤。在 TRPC 架构下,"缺鉴权"不是一个孤立事实,而是一个相对事实——同路由兄弟 procedure 都挂了鉴权中间件、新 procedure 没挂,或者兄弟查询都带 userId 过滤、新查询没带,才构成发现。这把主观的"这里好像没鉴权"变成了可执行的对比检查。

2.3 敏感数据进日志

Sensitive data in logs: API keys, tokens, credentials, full request bodies in console.* / debug() output No base64 blobs printed to terminal output (freezes output, may embed secrets)

两条针对日志面:API 密钥、令牌、凭证、完整请求体出现在 console.* / debug() 输出中;以及终端输出中打印 base64 大 blob——后者既会卡死输出,还可能间接嵌入密钥。在 CLI 应用(apps/cli/)和开发脚本尤其值得盯。

2.4 硬编码密钥与 NEXT_PUBLIC_* 暴露面

Hardcoded secrets — must come from environment variables New env vars holding secrets must not be exposed client-side (NEXT_PUBLIC_* review)

密钥必须来自环境变量;新增的、承载密钥的环境变量不得以 NEXT_PUBLIC_ 前缀暴露到客户端包中。检查项明确要求对 NEXT_PUBLIC_* 做专门复核。

2.5 SSRF

SSRF: user-controlled URLs fetched server-side without allowlisting

服务端抓取用户可控 URL 且没有白名单防护,是 SSRF 检查项。本仓库对此有现成的基础设施(见第 5 节 packages/ssrf-safe-fetch)。

2.6 业务槽位保密(Business-slot confidentiality)

src/business/ and packages/business/ must not expose commercial logic, pricing, or private infrastructure details in code or comments — slots export only minimal generic contracts and safe defaults

这是 LobeHub 特有的规则:src/business/packages/business/ 两个目录(在本仓库中真实存在)是"业务槽位",开源侧只允许导出最小化的通用契约和安全默认值,不得在代码或注释中暴露商业逻辑、定价、私有基础设施细节。它把"开源仓库里什么不该出现"这一通常靠自觉的约束,变成了一条可检查的清单条目,并配套了专门的操作方法(见 3.2 第 4 步:像外部贡献者一样读这些文件的 diff)。

3. 规则来源与检查流程

3.1 Rule sources

维度文件声明了 deep 模式评审者在开始评审前必须读的规则来源:

  1. 仓库根 AGENTS.md 的 security 相关章节(业务槽位、密钥文件);
  2. diff 所新增内容的"邻居实现"——相邻 procedure 的鉴权模式是判定"缺失鉴权"的标尺。

3.2 How to check:四步执行法

维度文件给出的操作流程可直接照搬执行:

  1. 追源到汇(trace to sinks):把每个新增外部输入(请求参数、用户内容、webhook 载荷、env)一路追到它的 sink,寻找未转义/未校验的跳板;
  2. 对比兄弟实现:对每个新 procedure/路由,打开同一 router 下两个相邻实现,对比中间件与用户范围过滤;
  3. 模式搜索:在 diff 上用 rgconsole.debug(NEXT_PUBLIC_dangerouslySetInnerHTML、原始 sql 模板用法——这五个模式正是 2.1–2.4 检查项的可机器化特征;
  4. 业务槽位外审视角:读 src/business/ / packages/business/ 的 diff 时"像外部贡献者一样"问一句——任何名称、注释、常量是否在泄露私有商业行为?

3.3 Violations 与 Not violations:判定的对称规则

构成违规(Violations):

  • 快速清单中任何一条,且"可被攻击者触达,或在开源仓库中可见";
  • 鉴权/范围过滤弱于既有的兄弟实现模式。

不构成违规(Not violations)——这部分同样重要,防止评审过度报警:

  • 输入在上游已被完全约束(例如在边界处校验过的 enum)——但必须先验证该约束存在再排除,并在报告中引用它(cite it);
  • 密钥存放在仅本地、且被 gitignore 的文件中("引用其文件名本来就是它的职责")——但必须确认该文件确实被 gitignore

这种"违规/非违规"对称书写配合 verify: true,构成了 deep-review 反幻觉设计的一部分:评审者负责带证据上报,独立 verify 子代理负责先找反例(上游保证、提前返回、框架行为、既有校验)再下 confirmed / false_positive / need_more_context 三态裁决,且每个确认结论必须有 file-and-line 证据。对安全类发现,verify 提示词中 blocks_release 的定义把 "security/auth failure" 明确列入"必须阻塞发布"一类(verify-prompt.md)。

4. 两种评审模式下安全维度的加载方式差异

模式 触发 安全维度做什么
Light(默认) 任何普通评审请求:"review this PR"、贴 diff 让你看问题 一个独立评审者完整读取本文件的 Quick checklist(含嵌套示例小节);裁剪表同样适用——仅 lockfile/generated-only diff 不跑安全项
Deep 显式调用(/deep-review、"run deep review") 评审子代理通读本文件全量,再按"Rule sources"一节读取 AGENTS.md 相关章节与邻居实现;发现进入按维度流水线的独立 verify 环节;安全维度因 calibration_exempt: true 在校准时不做先例降级

值得注意的是裁剪表对"docs-only"的界定:面向人类的纯散文才算文档;而 .agents/skills/**AGENTS.md / CLAUDE.md、prompt 模板这类"写给 agent 的可执行指令"在裁剪意义上等同于代码——它们的"散文"承载控制流与契约。因此一份修改了 agent 指令文件的 diff 永远不会被当作 docs-only 而绕过安全审查。

5. 规则与仓库实现的互证:以 SSRF 防护为例

检查清单里"SSRF: user-controlled URLs fetched server-side without allowlisting"这条,在仓库中有直接的实现级对应物:packages/ssrf-safe-fetch。该包为服务端提供一个基于 request-filtering-agent 的 SSRF-safe fetch,其 SSRF0ptions 接口(实际为 SSRFOptions,见 index.ts#L8-L24)定义了三个可配置项:

export interface SSRFOptions {
  /** List of IP addresses to allow */
  allowIPAddressList?: string[];
  /** Whether to allow private/local IP addresses */
  allowPrivateIPAddress?: boolean;
  /**
   * Maximum response body size in bytes. ... Use this for any fetch that
   * downloads untrusted content (e.g. web crawlers) ...
   */
  maxContentLength?: number;
}
  • allowIPAddressList / allowPrivateIPAddress 正是清单中"allowlisting"要求的服务端落点:默认拒绝私网/本地 IP,显式白名单才可放行;
  • maxContentLength 配合 readBodyWithCap 对响应体做软截断(读满上限即中止流并释放连接),防止抓取不可信内容时无界缓冲撑爆内存——这是 SSRF/抓取链路上"资源耗尽"的配套防护;
  • 同目录的 index.test.ts 提供了该行为可回归测试的依据。

也就是说,当 deep-review 安全维度审到"新增一个服务端抓取用户 URL"的 diff 时,"兄弟实现标尺"(Rule sources 第 2 条)会指向这类既有防护:新代码若直接 fetch(url) 而不经过带白名单与截断的受控 fetch,就构成"弱于既有兄弟模式"的违规。同理,清单中的 TRPC 鉴权对比、原始 sql 模板检查,分别以 apps/server/ 中既有的 router 模式和 packages/database/ 的 Drizzle 用法为校准基线——安全项虽豁免先例降级,但"用什么做标尺"依然来自仓库内真实实现。

6. 实战要点小结

  • 写 diff 时:新增外部输入先想 sink(SQL 模板、shell、dangerouslySetInnerHTML、路径拼接);新增 TRPC procedure 对照同 router 邻居补鉴权中间件与 userId 范围过滤;密钥只进环境变量且永远不挂 NEXT_PUBLIC_ 前缀;服务端抓用户 URL 走 packages/ssrf-safe-fetch 这类带白名单的受控入口;src/business/packages/business/ 里不写商业逻辑、定价与私有基础设施细节。
  • 做 i18n/文案变更时:不要以为"只是文本"——文档、文案、注释同样是泄漏向量,安全维度对纯文本变更照常运行,这是 skip_when 字段唯一收窄到 lockfile/generated-only 的原因。
  • 评审时:light 模式完整读 Quick checklist;deep 模式先读 AGENTS.md 安全相关章节与邻居实现,按四步流程执行,并用 rg 的五个模式词兜底;记住豁免规则的方向性——"存量代码里也有同样弱点"不是安全问题的减分项,而"上游已约束输入"才是合法的非违规理由(且必须引用约束出处)。

安全维度文件虽短,但它把一个 LobeHub 式的多端 AI 产品(Web、Electron 桌面端、CLI、Hono 后端服务,见 AGENTS.md 项目结构一节)中最常见的三类事故——注入、越权、泄漏——压缩成了可执行、可验证、可豁免判定的规则集,并通过 calibration_exemptverify: true 的组合,确保这些发现在整条评审流水线中既不被先例稀释、也不被模型臆断。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
504
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384