密钥绝不可硬编码在 composer.json 或 scripts 中,必须通过环境变量注入并用 PHP 脚本读取;本地、CI/CD、Docker、Web 服务器需分别安全传递环境变量,并在脚本开头校验密钥存在性。

别把密钥写进 composer.json 或脚本里——Composer 本身不提供加密或安全存储机制,所有敏感信息必须通过环境变量注入,且需确保环境变量在运行时可用、不被日志泄漏。
为什么不能在 scripts 中硬编码密钥
Composer 脚本(如 "post-install-cmd")是纯字符串,会被直接解析执行。一旦密钥写死在 composer.json 中:
- 它会随代码提交到 Git,极易泄露
- 即使加了
.gitignore,composer.json本身通常要提交,无法忽略 - CI/CD 日志可能完整打印执行命令,密钥明文暴露
-
composer dump-autoload -v等调试命令也可能回显脚本内容
正确做法:用 $_ENV 或 getenv() 在 PHP 脚本中读取
Composer 支持调用 PHP 函数或类方法作为脚本,这是唯一可控、可审计的密钥使用方式:
- 在
composer.json中定义脚本指向一个 PHP 方法,例如:"scripts": { "deploy": "App\\Script::runDeploy" } - 在
App\Script::runDeploy()中用getenv('API_KEY')或$_ENV['API_KEY']获取值 - 确保 PHP 配置中
variables_order包含"E"(即启用$_ENV) - 避免用
exec("curl -H 'Authorization: Bearer $KEY' ...")拼接命令——shell 注入和日志泄露风险极高
环境变量如何安全注入到 Composer 运行环境
Composer 启动时继承父进程环境,但不同场景下变量可见性不同:
- 本地开发:在 shell 中
export API_KEY=xxx后再运行composer run deploy—— 变量有效 - CI/CD(GitHub Actions):必须在
env:块中显式传入,且勾选 “mask secrets in logs”(但仅对secrets.*有效) - Docker:用
-e API_KEY=xxx或--env-file,切勿写进Dockerfile或构建阶段 - PHP-FPM / Apache:默认不继承 shell 环境变量,需在池配置中用
env[API_KEY] = xxx显式设置
额外防护:检测缺失密钥并快速失败
不要让脚本在无密钥时继续执行或报模糊错误。在 PHP 脚本开头强制校验:
public static function runDeploy()
{
$key = getenv('API_KEY');
if (!$key || strlen($key) < 12) {
throw new RuntimeException('Missing or invalid API_KEY in environment');
}
// 继续后续逻辑
}
这种检查能避免因变量未设置导致的静默失败,也防止空字符串被当作有效凭据发送出去。注意:某些 CI 平台(如 GitLab CI)在未定义 secret 时会注入空字符串而非 false,所以 empty() 不够可靠,需结合长度或格式判断。










