只加--no-scripts无法防住恶意插件执行,必须与--no-plugins联用才能真正切断Plugin::activate()等硬编码逻辑;该参数仅跳过composer.json中scripts字段定义的标准钩子(如post-install-cmd),对插件内嵌代码无效。

只加 --no-scripts 无法防住恶意插件执行
很多人以为加了 --no-scripts 就安全了,结果 CI 日志里没看到 Running script,但 public/ 下还是多出可疑 PHP 文件。这是因为 --no-scripts 只跳过 composer.json 的 scripts 字段定义的钩子(比如 post-install-cmd),对插件在 Plugin::activate() 或 executeCommand() 里硬编码的逻辑完全无效。像 symfony/flex 或私有源认证插件,会直接调用 shell_exec() 或写文件——这些根本不在 scripts 配置里。
必须同时加 --no-plugins 才能真正切断这类路径。命令必须写成:composer install --no-scripts --no-plugins --no-interaction,参数顺序不能错:--no-scripts 和 --no-plugins 必须紧贴 composer install 后面,否则会被忽略。
哪些脚本会被 --no-scripts 拦住,哪些不会
--no-scripts 只影响 composer.json 中 scripts 字段明确定义的标准生命周期事件:
-
post-install-cmd、pre-update-cmd、post-autoload-dump等官方命名的钩子,全跳过 - 第三方包自己写的
post-package-install(Composer 2.2+ 默认启用),也会被压制 - 自定义脚本名(比如
"build": "npm run build")不会被自动触发,所以谈不上“跳过”
但它不拦以下行为:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- vendor/bin 下已存在的可执行文件(如
phpunit、larastan),仍可被手动调用 - 通过环境变量注入的恶意参数(如
"post-install-cmd": "sh -c 'eval $MALICIOUS'") - autoload-dev 加载的测试类中隐藏逻辑,在
phpunit运行时才触发
跳过脚本后,哪些关键动作没了,得手动补
--no-scripts 不影响 vendor/autoload.php 生成,也不跳过依赖校验或平台检查(比如 ext-mbstring missing 该报错还是报错)。但它确实会让一些框架依赖的初始化动作消失:
-
post-root-package-install没跑 →.env.example不会复制成.env→ 应用读不到配置,报错静默 -
post-autoload-dump被跳过 → Laravel 的优化类映射没生成 → 启动慢、Class not found风险上升
CI 中用了 --no-scripts,后续步骤必须补上:cp .env.example .env 和 composer dump-autoload -o,否则测试环境行为和线上不一致。
更可靠的长期防护不是靠参数,而是清空 scripts 字段
命令行参数容易漏,尤其本地开发或 CI 配置不一致时。最稳妥的做法是在项目级让脚本“根本不存在”:把 composer.json 的 scripts 设为空数组:
"scripts": {
"post-install-cmd": [],
"post-update-cmd": [],
"pre-autoload-dump": [],
"post-autoload-dump": []
}
注意:null 或 false 无效,Composer 会忽略并回退到默认行为;空数组才是唯一被识别为“无操作”的值。清空后需手动运行 composer dump-autoload --optimize 替代框架依赖的钩子,否则性能或加载会出问题。

















