vendor目录禁用777,因composer.lock和vendor/composer/*.json等元数据文件是信任锚点,写权限可被利用篡改依赖、注入恶意包或劫持autoload;必须设为644(文件)和755(目录),备份/传输/解压后需用chmod或tar参数强制收紧权限。

vendor 目录不能设 777,哪怕只是临时备份元数据(如 composer.lock、vendor/composer/installed.json)也必须同步收紧权限——因为这些文件一旦被篡改,就能绕过依赖锁定、注入恶意包路径或劫持 autoload 流程。
为什么备份元数据也要管权限?
很多人以为只有 vendor/ 下的 PHP 文件才需防护,其实 composer.lock 和 vendor/composer/ 里的元数据文件是 Composer 运行时的“信任锚点”。攻击者若能写入 composer.lock,就能把合法包替换成同名恶意镜像;若能修改 installed.json,就可能让 class_exists() 加载到伪造类。这些操作不需要执行权限,只要文件可写即可生效。
-
composer.lock必须是644:防止被覆盖或追加恶意 package 块 -
vendor/composer/目录本身需755,但其下所有 JSON 文件(如installed.json、autoload_static.php)都应为644 - 若用 rsync 或 tar 备份后恢复,会继承源端权限 —— 比如从 CI 机器(root 用户)打包过来的
composer.lock默认是600或664,部署到生产机后得立刻修复
备份脚本里怎么自动收紧权限?
别等出事再手动 chmod。在打包前或解压后加几行权限加固命令,成本极低但效果明确:
- 备份前统一清理写权限:
find . -name 'composer.lock' -o -path './vendor/composer/*.json' -exec chmod 644 {} \; - 用
tar打包时禁用权限保留:tar --no-same-permissions --no-same-owner -czf backup.tgz composer.lock vendor/composer/ - 解压后强制重置:
tar xzf backup.tgz && find vendor/composer/ -type f -name '*.json' -exec chmod 644 {} \;
CI/CD 中容易忽略的权限断点
很多团队在 GitHub Actions 或 GitLab CI 里用 composer install --no-dev 生成 vendor/,却忘了这一步产生的元数据文件权限由 runner 用户 umask 决定。默认 umask 002 会导致 installed.json 是 664,组内成员可篡改。
- CI 脚本开头加:
umask 0022(确保新建文件为644,目录为755) - 安装后立即加固:
chmod 644 vendor/composer/installed.json vendor/composer/autoload_classmap.php - 禁止在 CI 中运行
composer update:它会重写composer.lock,且不校验权限
真正麻烦的不是 chmod 命令本身,而是元数据文件没有执行位却仍能被 PHP 解析——这让很多人误以为“没 x 就安全”,结果忽略了写权限才是关键攻击面。每次备份、传输、解压后,都该把 ls -l 当成检查清单的第一步。


















