一周让 YASA 端到端支持 PHP
作者:时绍森
蚂蚁集团高级安全工程师,YASA团队技术一号位。主要从事静态程序分析及其相关技术的研究工作,专注于利用静态分析技术解决多语言代码的安全漏洞发现、风险识别等关键问题。
背景:某战略业务急需 PHP 静态分析能力,业界相关产品的遗漏/误报双高且不支持自定义规则,按过去经验YASA自研新语言"季度起步"。本文记录我们是如何应用AI能力把它压到周级、完成对业务的支撑。
一、为什么是 PHP,为什么是一周
我们的具体场景是:某战略业务急需 PHP 静态分析能力,业界标杆产品在动态语言上的遗漏/误报双高且不支持自定义规则;按过去经验自研一门新语言"季度起步"。
我们用一周走完了"PHP 从 0 到引擎能力支持 → 业务代码库框架适配 → 规则定制 → 自动化运营"整条链路,结果验收:
- 靶场(开源 xAST 评价体系)准召率 95%+
- 团标《金融业应用安全测试产品检测能力评估准则·SAST 部分》达到 3 级成熟度
- 首轮全量扫描在真实业务代码库里跑出 3900+ finding,Agent 自主 triage 后人工最终确认了 490+ 条可利用漏洞链路
为什么 PHP 不能让"AI 直接看 PHP 代码"?
因为研发流程要的是硬卡点——CI 几分钟内必须出结果、必须可阻断、必须有可解释的 source→sink 链路。这是 SAST 几十年沉淀下来的工程位置,一个智能体跑十分钟给一段自然语言判断,进不去发布闸门。命令注入、SQL 注入、SSRF、XXE、文件包含、反序列化这些有明确语义模式的高危漏洞,引擎跑过程间污点分析就能给出确定性结论,比让 AI 一条条"理解再判断"更准、更快、更便宜。
而 PHP 是出了名的"语法复杂 + 持续演进 + 弱类型 + 包/模块机制特殊"的动态语言。要把这门语言接到一套已有的多语言静态分析引擎上,需要解决的不是"AI 写 parser"这么简单的问题,而是整条链路:UAST 前端 → 引擎语义适配 → 业务框架建模 → 规则配套 → 漏洞运营。下面按这条链路展开,但在进入具体五阶段之前,先讲讲 PHP 这件事是怎么组织起来的。
二、PHP 接入不是"AI 黑盒 Coding",而是"AI 沿专家路径"
先讲一个反例。
如果你把一个高复杂度的统一多语言 SAST 引擎代码丢给 AI,说"帮我加 PHP",结果几乎一定是:AI 在引擎里东改西改、随手添加 PHP 专用 hack、污染共享的底层引擎,跑出来的 PHP 数字看似漂亮,回到 Java/Go/Python 一测全是回归问题。这条路我们实验过,走不通。
PHP 这次能跑通的是另一条路:把"跨语言建设"这件事本身抽象成一份 AI 可执行的标准路径,让 AI 沿着专家走过的路落地,而不是让 AI 拿着代码自由发挥。
我们把这件事写成了一份 skill(你可以理解为给 AI 看的 SOP),核心就是 PHP 这次实际走的这张图:
① UAST parser 完备
↓
② Benchmark + 成熟度 case 设计(xAST 评价体系 / 团标对齐)
↓
③ 所有 Checker 原子化检出能力补齐(通用层适配,不污染底层)
↓
④ 目标代码库框架适配(业务框架 entrypoint / source 建模)
↓
⑤ 自动化运营(triage agent + 规则反哺闭环)
每个阶段有:目标、验收口径、典型坑、跨仓库提交边界、Worker 拆分建议。skill 里还沉淀了一份"高发陷阱表"——比如 npm link 改完不重编译会读到旧产物、runtime.execute 覆盖默认 passthrough 导致 taint 断链、文件级 entrypoint fallback 会让动态语言产生重复 finding……这些都是过去多语言建设里踩过的坑,写成显式规则就能让 PHP 这次第一轮就避开。
PHP 这件事的关键不在 AI 多聪明,而在我们把"专家经验"显式化、结构化、可被 AI 执行——AI 只是沿着这条路把 PHP 走完一遍。
三、PHP 这周谁在干活:虚拟 AI Team
PHP 这一周,YASA工程师数字分身组织了一个虚拟 AI Team 来落地:
Partner(战略 / 路线 / 全局看板)
↓ DIRECTIVE.md
Task Leader(拆任务、调度 Worker、review、合并)
↓ TaskCreate + Agent spawn
Worker × N(侦查 / 实现 / 测试 / triage)
Leader 收到一个 PHP 子任务(比如"补 trait 方法解析"或"靶场二级 case 扩充"),第一步不是动手,而是先拆——按文件、按子能力、按 case 分组并行交给 ≥2 个 Worker。Worker 在隔离的 worktree 里干活,每 30 分钟回报一次结构化进度,被阻塞立刻 ping。Leader 自己只做几件事:拆分、调度、审查 Worker 的代码、合并到 PHP 任务分支、回写状态。
这套架构解决了 PHP 这次面对的一个非常实际的问题——单一 AI Context 装不下"PHP UAST + 引擎适配 + 五大类 checker + 业务框架 + 运营智能体"的全貌。把上下文压力分摊到多个 Worker,每个 Worker 只关心自己的小切片,Leader 维护全局看板。
PHP 这次一周里,我作为人类只做了几件事:
- 在关键路口做技术判断("这个能力是该进通用层还是 PHP 语言层")
- 在数字异常时质问("你这个 PHP 召回提升的口径是什么")
- 在 AI 走错方向时拉回来("不要在引擎底层加 PHP 专用分支")
其他全部是 AI Team 自己跑。
四、阶段 ① — UAST parser:把 PHP 的"骚操作"翻译成统一中间表示
PHP 从早期的面向对象,到后续的类型提示、nullsafe、constructor promotion、match 表达式、readonly 属性、非捕获 catch……每一版都在加新糖。
YASA 用一套统一的 UAST(Unified AST)覆盖所有语言。这一阶段的工作是写 parser-php:把 PHP 源码经 tree-sitter 解析后,按 UAST schema 输出干净、无歧义的中间表示。
PHP 在 UAST 翻译这一步踩到的"语法糖"非常多,我们把它们整理成了一份修复模式表:
|
类别 |
表现 |
修复模式 |
|
隐式 self |
|
显式输出 ThisExpression |
|
构造函数标记 |
构造函数没打 isConstructor |
按命名约定( |
|
Constructor Promotion |
参数直接声明为字段 |
UAST 层补齐 |
|
tree-sitter field 缺失 |
|
改用 |
|
Trait/继承 |
关键字节点未并入 supers |
supers 数组拼接 |
这套修复模式不是 PHP 特有的——很多动态语言都会撞上类似问题。我们把它沉淀进 skill,下一门动态语言接入时第一轮就能避开 80% 的陷阱。
五、阶段 ② — 靶场建设:把"准召率"和"成熟度"做成可重复的 gate
光把 parser 跑通不算数,必须有可重复的评测基线。这一阶段我们在开源 xAST 评价体系下建了完整 PHP 靶场:
- 按 accuracy + completeness 两大类组织
- 按 1~4 级成熟度 分层
- 每个 case 配
_T(应检出)/_F(不应误报)和 evaluation info
最终成绩:
- 团标《金融业应用安全测试产品检测能力评估准则·SAST 部分》PHP benchmark 达 3 级成熟度
- 开源 xAST 准召率 95%+
这两个数字不是手工统计的——是 calculate-maturity 工具基于 expect 基线算出来的,每次回归都可复算。后续任何引擎改动都能直接看到 PHP 准召率的 delta,不会"改完不知道有没有退化"。
工程纪律:靶场 case 必须落在公开仓库,禁止出现内部业务名/真实接口路径,这条边界在 PHP 这一轮严格守住了。
六、阶段 ③ — Checker 全栈:在 YASA 多语言通用引擎上补齐 PHP 语言层
这是 PHP 接入工作量最重、最考验工程方法的一步。
YASA 的污点分析引擎是语言无关的,核心能力(过程间数据流、上下文敏感、对象与字段敏感、流敏感与路径敏感、别名分析)一旦在 UAST 上生效,就同时服务所有语言。PHP 这一阶段的工作,是在 YASA 多语言通用引擎之上补齐 PHP 的语言特性和包/模块管理机制,让 PHP 自动继承引擎的污点追踪、callgraph、callchain 等通用能力——而不是为 PHP 重写一套分析框架。
具体补齐了五块:
- 污点源登记:把 PHP 的超全局变量这类天然用户可控输入纳入引擎的 source scope,污点链路从入口就接得上
- 包/模块管理:跨文件 include/require 翻译成同一作用域的延续,跨文件定义的函数、类、sanitizer 自然进入同一条数据流——这是模式匹配类工具天然做不到的边界
- 面向对象语义:对象/字段敏感、继承与 trait 的方法解析、魔术方法作为隐式调用点
- PHP 标准库行为建模:对没有源码的内置函数预先给出 passthrough / sanitize / source 先验,避免污点一接触标准库就断链
- 引用与别名:PHP 的引用传参、别名赋值、数组下标别名打通到引擎已有的别名分析
这五块支撑起来之后,污点追踪、callgraph、callchain 这些重型能力在 PHP 上就直接可用了。
铁律:所有 PHP 特判(弱类型 calleeType 通配、按引用语义、魔术方法分派)只能落到语言层(<lang>-analyzer / <lang>-default-taint-checker),禁止污染底层共享引擎。每次试图在底层加 if (lang === 'php') 都会在 review 时被打回——这条纪律守住了"加 PHP 不让其他语言回归"的底线。
七、阶段 ④ — 业务框架适配:让引擎"懂业务代码长什么样"
光有 PHP 语言层不够。真实业务代码里,"用户可控输入"和"接口入口"都是经过框架封装才出现的,不是赤裸的超全局变量。
PHP 这次在业务代码库里需要做两件事:
- Source 适配:业务里大量的
getParam / getHeader / getUnSafeData这类包装方法才是真正的用户可控输入起点。我们用一个 Source 识别 Agent自动扫描业务代码、识别这类 getter 链路、产出 source 配置,再人工 review 一遍。 - Entrypoint 适配:业务里同时存在标准 MVC Controller、内部 SOA 服务接口、自研的跨应用数据集散组件。每一类都有自己的基类/目录/注解特征。引擎层暴露了"Entrypoint Collector"扩展点,PHP 业务里每种框架对应一个 collector 文件,互不耦合。
这一步的关键在于理解一份从没见过的业务代码库的框架风格,并把理解转化成可执行的 collector + source 配置——这是 PHP 这次最贴近业务的一段工作。
八、阶段 ⑤ — 漏洞运营:从"扫一次"到"持续闭环"
企业级 SAST 的真正难点不是"扫描",是"扫完之后怎么办"。PHP 首轮跑出 3900+ 条 finding,人工逐条看就是几个月。
我们用一个漏洞运营 Agent把这一步闭环:
- 逐条 triage(禁止抽样、禁止族级推断),状态枚举:
exploitable / not-exploitable / unreachable / deadcode / duplicate-of:<id> - 每条卡片记录:source / sink / caller 状态 / 可利用性 / 置信度
- 历史标签复用:前轮 confirmed 的真阳性直接采纳
- 真实漏洞产出结构化报告,含 CWE / 严重度 / source→sink 跳链 / 一句话危害描述
- 反哺规则:SARIF dedup、新 sink 发掘、sanitizer 收敛——每条规则改动 → 类型检查 0 + 全语言 benchmark 回归 + 原项目重扫 delta 可解释
PHP 这次首轮跑了 3900+ 条 finding,Agent 自主 triage 后人工最终确认了 几百条 可利用漏洞,真阳性率约 12.8%(业界 SAST 工具典型水平)。涵盖命令注入、代码执行、SQL 注入、SSRF、XXE、文件包含、文件读取、任意文件上传、HTTP 头/日志注入九类高危场景。其中包含几条 CRITICAL 级未鉴权 RCE 后门入口——这是任何模式匹配类工具都难以发现的语义级链路。
九、PHP 这次留下了什么
PHP 这一周不是只交付了"PHP 能扫"这一件事,这次建设的 PHP 语义能力,会直接成为后续 PHP 代码审计智能体的底座:
- PHP UAST:把所有语法糖归一到统一中间表示——后续 PHP 智能体读 UAST 比读源码更稳定、更短、更省 token
- 过程间调用图、跨文件 include/require、虚表方法解析、魔术方法分派:智能体直接复用,不用自己重建
- 对象/字段敏感的污点流、超全局污染源、框架 entrypoint:智能体拿来当"业务上下文"的输入
- Source 自采集 Agent、漏洞运营 Agent:本身就是智能体形态,可以直接长出"水平越权检测 Agent"等业务逻辑类能力
也就是说:SAST 守研发上线卡点的硬规则,智能体在 SAST 语义能力之上做业务逻辑类漏洞——水平越权、垂直越权、业务流程绕过这些没有固定语法模式、需要"理解业务语义"的漏洞,正是智能体能发挥的地方。两条战线分工清晰,共用一份语义底座。
PHP 这次把底座建好了,下一步在这个底座上长 PHP 代码审计智能体,边际成本比"从零理解 PHP 代码"低一个数量级。
十、写在最后
PHP 一周端到端支持上线,不是"AI 突然能很好的写YASA代码了",是几件事在 PHP 这次同时成立:
引擎的通用层在 PHP 之前就已经语言无关、跨语言建设经验已经显式化成可执行的 SOP、Source/Triage 这些 Agent 在 PHP 之前就已经做出来可复用。PHP 这次只是把这些既有资产用到一门新语言上,再把 PHP 特有的语言特性和包/模块机制按既定路径补齐。
点击了解【开放式统一多语言程序分析产品YASA】
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)