Composer install/update 自动执行脚本存在远程代码执行等安全风险;应使用 --no-scripts 参数禁用 scripts 字段定义的钩子,但不影响 autoload 生成及插件逻辑。

Composer install/update 时脚本自动执行的风险在哪
默认情况下,composer install 和 composer update 会自动运行 post-install-cmd、post-update-cmd 等脚本。这些脚本可能执行任意 PHP 代码(比如生成 autoload 文件、清缓存、甚至调用外部命令),在不可信的依赖或被污染的 composer.json 场景下,存在远程代码执行(RCE)或本地提权风险。
典型触发点包括:从第三方 fork 仓库安装依赖、CI/CD 中拉取未审核的分支、或使用了带恶意钩子的私有包。
如何彻底禁用所有脚本执行
用 --no-scripts 参数是最直接的方式,它会跳过所有 scripts 部分定义的生命周期钩子,包括 pre-*、post-*、pre-package-install 等。
-
composer install --no-scripts:跳过post-install-cmd等,但依然会生成vendor/autoload.php(这是 Composer 自身行为,非脚本) -
composer update --no-scripts:同样跳过所有 update 相关钩子 - 该参数对
composer require和composer remove同样有效 - 注意:
--no-scripts不影响插件(plugin)自身的逻辑,只禁用composer.json中scripts字段定义的内容
什么时候必须加 --no-scripts
不是所有场景都需要禁用脚本,但以下情况建议强制加上:
- 在生产环境部署时,你明确不需要任何 post-install 逻辑(例如无缓存需清理、无配置生成)
- 审计第三方依赖前,先隔离其脚本行为(配合
--no-autoloader可进一步减少副作用) - CI 流水线中拉取未经签名的 tag 或 commit,且构建阶段不依赖脚本输出
- 遇到类似
Script ... handling the post-update-cmd event returned with error code 1的报错,又不想临时修改composer.json
常见误区与兼容性注意
--no-scripts 看似简单,但几个细节容易踩坑:
- 它不会跳过
autoload生成 —— 这是 Composer 核心流程,和脚本无关;若要跳过,得加--no-autoloader - 某些包(如 Laravel 的
laravel/framework)依赖post-autoload-dump生成优化后的 classmap,禁用后可能导致性能下降或类加载失败 - 在 Composer 2.2+ 中,
--no-scripts对composer create-project同样生效,但部分模板项目会因此无法完成初始化(如 Symfony 官方 skeleton) - 不能通过
COMPOSER_NO_SCRIPTS=1环境变量替代 —— Composer 不识别该变量,必须显式传参
安全边界其实很窄:脚本禁用只解决“谁执行”的问题,不解决“执行什么”。如果某个包在 src/ 里直接写了 exec('rm -rf /') 并被 autoload 加载,--no-scripts 完全无效。










