allow-plugins白名单必须固化于composer.json的config节点,不可临时添加或用环境变量绕过;需显式授权如"symfony/flex": true,严格格式无注释、无尾逗号,发布前须--dry-run验证并补全二级依赖。

allow-plugins 白名单必须在发布前固化进 composer.json
插件白名单不是 CI 脚本里临时加的开关,它必须作为项目配置的一部分提交到仓库。一旦你用 composer require symfony/flex 引入带插件的包,Composer 就会报错并中止安装——除非 config.allow-plugins 已提前声明该包名。发布流程里漏掉这一步,下游用户 clone 代码后直接 composer install 就失败。
常见错误现象:Plugin installation failed: Package "symfony/flex" cannot be installed as it is not allowed by your allow-plugins config
- 白名单必须写在
composer.json的config.allow-plugins下,不能塞进extra或scripts - 格式必须严格:无注释、无尾随逗号、键名全小写、值为布尔字面量(
true,不是"true") - 示例正确写法:
"config": { "allow-plugins": { "symfony/flex": true, "laravel/pint": true } } - 发布前运行
composer install --dry-run验证是否仍被拦截;若还报错,说明有二级插件依赖(比如某个 scaffold 工具内部又 require 了另一个插件),得顺藤摸瓜补全
发布私有包时,白名单要和 packagist.org 的验证逻辑对齐
如果你的包本身是插件(即实现了 Composer\Plugin\PluginInterface),且计划上架 Packagist,那么它的 composer.json 里不能含 allow-plugins 字段——Packagist 不解析这个字段,也不会帮你校验。但下游项目引用你时,仍需在自己的 composer.json 中显式授权。
关键点在于:Packagist 页面上显示的 “Verified” 标识,和你能否被信任加入白名单强相关。没有 Verified、LICENSE 模糊、GitHub stars <500、最近半年无提交的包,哪怕你把它发上去了,也不该放进生产项目的白名单。
- 发布前自查:运行
composer show yourname/your-plugin,确认输出含Plugin字样 - 翻源码重点看:是否调用
exec()、eval()、写入/tmp或vendor/外路径 - 不要依赖“我司内网托管就安全”——白名单机制不区分源,只认包名。内网镜像同步恶意 fork 同样生效
CI/CD 流程里不能靠环境变量绕过白名单
有人试图在 GitHub Actions 或 GitLab CI 里用 COMPOSER_ALLOW_PLUGINS=1 或 --no-plugins=false 来跳过检查,这完全无效。Composer 2.2+ 忽略所有此类环境变量或 flag,只认 composer.json 里的 config.allow-plugins 结构。
真正该写死的是 --no-plugins:它才是生产环境唯一可信的防护手段。
- CI 脚本中必须显式使用:
composer install --no-plugins --no-scripts --no-dev --prefer-dist - 别信 wrapper 脚本(如
bin/composer),它们可能悄悄加了--no-plugins以外的参数,导致行为不一致 - 如果发布流程包含构建 phar 或打包部署包,确保构建机也走
--no-plugins,否则插件可能在构建期注入额外逻辑
post-install-cmd 脚本和插件白名单是两套独立机制
很多人以为加了 "symfony/flex": true 就能跑通所有安装后动作,结果发现 post-install-cmd 里的 php ./artisan config:cache 还是没执行。这是因为:插件白名单控制的是“谁可以注册钩子”,而 post-install-cmd 是 Composer 自身事件系统,不经过插件注册流程。
它是否执行,只取决于两个条件:--no-scripts 是否开启,以及当前是否处于 --no-dev 环境(dev 包脚本默认禁用)。
- 白名单里加了插件 ≠
post-install-cmd自动生效;两者配置位置、触发时机、权限模型完全不同 - 验证方式:CI 中运行
composer run --list | grep post-install-cmd,能看到才说明注册成功 - 最容易被忽略的细节:
post-install-cmd在--no-dev下仍会执行(只要没加--no-scripts),但很多自定义脚本依赖 dev-only 包,所以实际失败常被误判为“白名单没起作用”


















