composer不具备静态代码审计能力,其插件机制仅提供有限钩子且不暴露源码内容;真正可行的静态审计需在install后用phpstan、psalm等外部工具扫描vendor目录,检测eval()、exec()等危险函数,并在ci中失败退出。

Composer 没有、也不可能存在“恶意插件静态代码审计系统”——它本身不扫描代码,也不提供静态分析能力。所谓“审计系统”若声称能自动识别 eval()、system()、base64 解码后执行、或混淆的反序列化链,那它一定不是 Composer 插件,而是独立工具(如 PHPStan、Psalm、RIPS 或自研扫描器),且必须绕过 Composer 的 PluginInterface 机制直接操作 vendor/ 目录下的文件。
为什么不能用 Composer Plugin 做静态审计
Composer 的 PluginInterface 在依赖安装流程中只有有限几个钩子,全部发生在包已下载、解压、autoload 注册甚至脚本执行之后。最靠前的 PRE_PACKAGE_INSTALL 事件虽能拦截,但它只暴露包元数据(name、version、dist URL、signature),不提供源码内容,更无法触发 AST 解析或字符串模式匹配。
常见错误认知:
- 以为在
pre-install-cmd里file_get_contents('vendor/xxx/src')就能审计——但此时目录还不存在 - 试图用
post-autoload-dump扫描已生成的vendor/autoload.php——这已是攻击者代码可执行的最后一步 - 把
composer audit当成代码扫描器——它只比对 CVE 数据库,不读任何 PHP 文件
真正可行的静态审计路径
必须脱离 Composer 插件生命周期,用外部命令直接处理 vendor/ 中的 PHP 文件。关键前提是:审计动作必须在 composer install 完成后、服务启动前执行,且失败时能中断 CI 流程。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
实操要点:
- 用
composer show --format=json --locked提取所有已安装包的路径(source.url或dist.path),过滤出type为library或project的包 - 对每个包的
src/、lib/、tests/(除非明确排除)目录,调用phpstan analyse或psalm --find-dead-code - 加自定义规则检测危险函数:例如 Psalm 的
ForbiddenCodeplugin,或用grep -rE "(eval|exec|shell_exec|system|passthru|proc_open|unserialize)" vendor/(注意跳过vendor/bin/和测试桩) - 把扫描结果转成 JSON 并提取
critical级别问题,用jq 'length > 0'判断是否需exit 1
容易被忽略的三个落地细节
很多团队写了扫描脚本却形同虚设,问题常出在:
-
composer install默认用--prefer-dist,而vendor/下全是 zip 解压产物——没有.git,也没有原始注释和调试代码,但恶意 payload 仍可能藏在autoload.files引入的单个 PHP 文件里,这种文件必须显式加入扫描范围 - 扫描器默认跳过
vendor/*/*下的tests/和examples/目录,但攻击者常把后门放在tests/Helper.php或examples/shell.php,需手动--include - CI 环境中
vendor/权限常为只读,导致phpstan缓存写入失败并静默跳过部分文件——必须加--configuration=phpstan.neon --no-progress显式指定配置和禁用进度条
真正的防线不在“装包时拦住”,而在“装完后立刻翻一遍源码”。别指望 Composer 自己做这件事,它连打开一个 PHP 文件的权限都没有。










