系列: 与 AI 一起学编程

一个周六早上的八项安全发现

八项安全发现,每一项都在周六晚上之前落地修复。

Eight Findings, One Saturday Enterprise due diligence, every one closed Input validation Hardcoded credential Cipher-suite policy Use-after-free Thread-safety Authz bypass Auth-failure logging Dependency lag 8 / 8 closed + 6 new permanent guardrails
欢迎审计的团队,才是代码库会变得更好的那个团队。

审计会把问题浮出水面。诚实的做法是欢迎它,修复一切,交付永久性的护栏——这正是一个运行时赢得企业信任的方式。

审计报告在上周末晚些时候到了收件箱。到周六早上,我一块屏幕开着报告,另一块屏幕开着代码库。八项严重或高危发现。这种收件箱内容足以定义一整个周末。

这是一次企业尽职调查。一个潜在合作伙伴要求他们的安全团队在律师推进之前,对我们的公开 API 表面做一遍审查。这些发现具体、解释清楚,而且完全合理。它们也正是那种,如果你不刻意防范,一个由智能体驱动的工作流会格外容易暴露出来的问题。

到周六结束时,每一项发现都有一个 PR 落地修复。这篇文章讲的就是每一项具体是什么。

分类是什么

我打算谈分类而不是具体的漏洞利用细节,因为具体细节现在已经修复,对竞争对手来说没有意义;而分类才是其他团队会想要防范的东西。

第一:公开 REST 表面上的输入校验。 若干端点对输入的信任程度超过了它们应有的水平。具体来说,是字符串输入的长度边界、数值输入的范围边界,以及 JSON 载荷的结构校验。这些缺失的校验单独看都不是灾难性的。但「这里没有长度边界,加上那里没有速率限制,再加上这个管理端点没有权限校验」这种组合,一旦被攻击者发现这个表面,就会变成灾难性的问题。

第二:配置文件中的一个硬编码凭据。 这和几个周末前那次 HMAC 发现不同。这是一个配置模板,在示例版本里提交了一个真实凭据。本意是发布一个作为占位符的示例凭据;实际发布出去的,却是一个来自某位开发者本地环境的真实值。处理方式是轮换、从示例中移除、并加入密钥扫描 CI 流程。

第三:不安全的密码套件协商。 一个与外部服务协商 TLS 的子系统,接受了在 2026 年不应再被接受的密码套件——具体来说,是若干个预 TLS-1.3、已知存在弱点的套件。修复方式是把密码套件列表约束为仅 TLS-1.3,并为针对遗留合作伙伴系统的测试保留一个有文档记录的例外开关(一个显式标志)。

第四:C API 边界的一个释放后使用(use-after-free)漏洞。 某个运行时 DLL 的 C API 里有一个函数,会返回一个指向内部状态的指针,而调用方在同一句柄上的后续调用释放了这个内部状态之后,仍然可以继续使用这个指针。这是经典的 C API 陷阱。修复方式是把语义从「调用方持有指针」切换为「调用方持有不透明句柄,配合一个按句柄取值的访问器」。这个访问器在调用期间返回一份新鲜的指针拷贝,底层内存不再对外暴露。

第五:授权层中的一个线程安全漏洞。 两个线程在并发验证调用期间,可能在同一个授权状态对象上产生竞态。在负载压力下,一个线程可能看到一个部分更新的状态,从而对授权是否有效得出错误结论。修复方式是围绕该状态加上一个恰当的读写锁,并针对常见情形(授权有效、无需状态变更)优化验证路径。

第六:一个管理端点上的授权绕过。 某个管理端点有身份验证检查,却没有授权检查。任何经过身份验证的用户都能调用它,包括没有管理员角色的用户。修复方式是加上角色检查,编写一个同时覆盖「以管理员身份验证——允许」和「已验证但非管理员——拒绝」两条路径的单元测试,并审计其他每一个管理端点是否存在同样的模式。另外三个端点也有同样的问题,现在这四个都已修正。

第七:身份验证失败时的日志记录不足。 当一个用户尝试身份验证失败时,运行时记录了这次尝试,但没有记录足够的上下文来调查暴力破解或撞库攻击模式。修复方式是在每次身份验证失败时添加结构化日志,记录 IP 地址、该 IP 的限速计数器,以及尝试使用的身份验证方式。这个方案保护隐私(不记录密码内容),但一旦需要调查,就有足够的上下文可用。

第八:依赖更新滞后。 运行时引入的若干第三方依赖,在清单中锁定的是已知存在漏洞的版本。修复方式是把每一个都更新到最新的已打补丁版本,针对更新跑一遍测试套件,并解决更新所需的少量 API 形状变化。八项更新中有两项需要在我们的代码里做适配器改动,其余六项都是即插即用。现在 Dependabot 已配置为自动标记这类问题。

我从这个安全工作周末中学到的东西

三件事,不算意外,但值得说出来。

安全发现是成簇出现的。 一次浮出八项发现不算少。回头看,这个模式是,它们都有一个共同的根源:这个运行时在一个由智能体驱动的工作流中快速成长,智能体们各自实现的东西在孤立看来都是正确的。像安全这样的横切关注点,恰恰是逐个 PR 评审会漏掉的那种东西。审计抓住的正是评审漏掉的部分。把审计排上日程。

有些发现是智能体驱动的失效模式。 C API 里的那个释放后使用漏洞,正是当提示词说「把这个内部状态暴露给调用方」而没有指明所有权语义时,智能体会写出来的那种东西。授权层的线程安全漏洞与此类似。两者抓住的是同一个模式:不被追问所有权和并发问题的智能体,写出来的代码会对这两者都置之不理。

有些发现是节奏驱动的失效模式。 依赖更新滞后不是一个智能体问题,而是一个「快速交付、却没有专人负责让依赖保持新鲜」的问题。修复办法是流程(Dependabot)和纪律(对 Dependabot 的告警采取行动),修复办法不是「变得更聪明」。

新增的防御措施

这个周末落地的永久性护栏。

CI 中的安全扫描环节。 针对输入校验、密钥扫描和密码套件策略的静态分析。每个 PR 都会运行这个扫描,引入新发现的 PR 会被标记出来供评审。

一种管理端点的测试模式。 API 里的每个管理端点现在都配有一对测试,同时覆盖「管理员允许」路径和「非管理员拒绝」路径。这个模式由一个 CI 检查强制执行,该检查会扫描 @admin_required 装饰器,如果该装饰器存在却没有对应的配对测试,构建就会失败。

共享状态上的线程安全注解。 运行时里的每一个共享状态对象,现在都带有一个关于其并发模型的显式注解:不可变、锁保护、带显式 happens-before 的无锁,或单线程。这个注解是类型的一部分。触碰该状态的代码必须满足这个注解。编译器对锁保护和不可变这两种情形强制执行检查,其余的靠评审把关。

日历上的每月安全审计。 不再等合作伙伴来问。审计现在是每个月第二个周六的固定安排,第一次将在四月运行。

合作伙伴和构建者应该从中得到什么

如果你正在评估一个引擎是否值得合作,并且打算要求做一次审计,这个团队会欢迎它。审计会把问题浮出水面,问题会被修复,代码库会变得更好,合作伙伴关系也会变得更好。欢迎审计这份纪律,比任何一项具体发现都更重要。

如果你是一位正在读这篇文章的企业安全从业者,我很乐意听取关于审计节奏的建议,以及你希望更多引擎团队去审计的具体事项。这个周末发现的都是显而易见的问题,那些不那么显而易见的问题,才是我接下来想要找到的。

如果你正在运行一个由智能体驱动的工作流,而且最近没有做过安全审计,去做一次吧。「智能体写出孤立来看正确、却遗漏横切关注点的代码」这个模式,在这种工作流形态下是普遍存在的。审计就是你抓住这些横切关注点的方式。我还没有找到别的办法。

周末结束时的核对:八项发现全部关闭,六项新防御措施落地,下一次审计已经排上日历。合作伙伴关系向前推进了一步。

回去继续构建。

一个能通过尽职调查的空间运行时

RakuAI 是为企业合作伙伴和智能眼镜制造商打造的——经过审计、经过加固,并对此坦诚相待。看看我们如何为你团队必须跨过的安全门槛做工程设计。

← 所有文章