APIkey泄露进git的三道防线

admin 2026-08-23 04:51:59 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文提出防止API密钥泄露进Git的三层防线:构建阶段通过envOr模式和环境变量文件避免密钥硬编码;运行阶段在启动和首次请求时检查空密钥并立即报错;代码审查阶段使用pre-commithook和CI扫描工具自动化检测,辅以人工复查。核心建议是密钥永远不应出现在Git历史中,三层防线协同可将泄露概率降至接近零。 综合评分: 90 文章分类: 安全开发,安全工具,安全意识,代码审计,解决方案


cover_image

API key 泄露进 git 的三道防线

一二 一二

后端一二事

2026年8月14日 18:13 北京

在小说阅读器读本章

去阅读

API key 泄露进 git 的三道防线

上周清理代码,差点把 API key 硬编码进 main.go 提交上去。envOr 拦住了,但这事儿让我想明白:防泄露得分三层守。

第一层:构建阶段——别让 key 进源码

envOr 模式

var (
    apiBase = envOr("API_BASE", "https://api.example.com/v1")
    apiKey  = os.Getenv("API_KEY") // 不给默认值,强制从环境变量读
)

func envOr(key, fallback string) string {
    if v := os.Getenv(key); v != "" {
        return v
    }
    return fallback
}

apiKey 为什么不用 envOr?因为它没有合理的默认值。写成 envOr("API_KEY", "sk-test123") 那个 fallback 迟早进 git。

.env.local + .gitignore

# .gitignore
.env.local
*.key
*.pem
# .env.local (不提交)
export API_KEY="sk-prod-xxxx"
export API_BASE="https://www.haoshuangapi.com/v1"
# start.sh (可以提交)
#!/bin/bash
set -a
source .env.local
set +a
exec ./docqa "$@"

set -a 让 source 的变量自动 export,set +a 关掉,别污染后续命令。

实际数据:我的 docqa 在 8 月 8 日前,API_KEY 写死在 main.go 第 31 行。改完后 grep -r "sk-" projects/docqa/*.go 返回空,密钥彻底出了源码。

第二层:运行阶段——空 key 要炸得响

启动时检查

func main() {
    if apiKey == "" {
        log.Fatal("API_KEY 环境变量未设置")
    }
    // 启动服务...
}

为什么不在 init() 里检查?log.Fatal 调 os.Exit(1),defer 不执行。后面加了 DB 清理,放 main() 开头安全。

第一次请求时检查

func callEmbedding(ctx context.Context, text string) ([]float64, error) {
    if apiKey == "" {
        return nil, fmt.Errorf("API_KEY 未配置,无法调用 embedding")
    }
    // 构造请求...
}

两层都检查,因为有些服务只在第一个用户上传文档时才调 embedding。只在启动检查,空 key 可能跑一周才暴露。

实际数据:8 月 8 日排查,API_KEY 环境变量是空的(printenv API_KEY 返回空),程序能跑是因为 main.go 第 31 行有 fallback 默认值 sk-xxx。只靠启动检查不够,调用时也得查。

第三层:代码审查——自动化 + 人工复查

pre-commit hook

#!/bin/bash
# .git/hooks/pre-commit

# 检查疑似 key
if git diff --cached | grep -E "(sk-[a-zA-Z0-9]{20,}|api[_-]?key.*=.*['\"][^'\"]{20,})"; then
    echo "❌ 检测到疑似 API key,请移除后再提交"
    exit 1
fi

这个正则只拦明文 key,拦不住 base64。更安全用 gitleaks[1] 或 truffleHog[2]。

CI 阶段扫描

# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
  gitleaks:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - uses: gitleaks/gitleaks-action@v2

开发者能 git commit --no-verify 跳过 pre-commit hook,CI 是最后一道。

人工复查

提交前跑:

git diff --cached | grep -i "key\|token\|secret\|password"

匹配到了先确认:

  1. 变量名还是实际值?(apiKey := 安全,apiKey := "sk-xxx" 不安全)
  2. 测试数据还是生产数据?("test-key-123" 能提交,真实 key 不行)
  3. 公开文档示例吗?(AWS 文档的 AKIAIOSFODNN7EXAMPLE 安全)

实际案例:docqa 的修复

8 月 8 日上午发现 projects/docqa/main.go 第 31 行硬编码了 API key。

修复步骤:

  1. key 从 main.go 删掉,改成 os.Getenv("API_KEY")
  2. 创建 .env.local,真实 key 写进去
  3. .gitignore 里加 .env.local
  4. 写 start.sh 脚本,source .env.local 后启动
  5. main() 开头加 if apiKey == "" { log.Fatal(...) }

核实方法(任何人可验证):

cd projects/docqa
grep -n "sk-" main.go          # 返回空
grep -n "apiKey.*=" main.go    # 只有第 31 行 os.Getenv("API_KEY")
grep -n "API_BASE" main.go     # 只有 3 处:定义 + 两次拼 URL

一个坑:apiBase 是 envOr("API_BASE", "https://..."),看着安全,但拼接是 apiBase + "/embeddings",所以 API_BASE 不能带尾斜杠,否则拼成 https://example.com//embeddings(双斜杠)。接入时唯一容易翻车的地方。

三层协同

| 防线 | 拦截时机 | 成本 | 覆盖率 | | — | — | — | — | | envOr + .env | 编码时 | 低 | 80% | | 启动/请求检查 | 运行时 | 低 | 90% | | hook + CI | 提交/合并前 | 中 | 95% |

为什么三层都要?每一层都有洞:

  • 第一层挡不住”先硬编码测试,忘了删”
  • 第二层挡不住”提交了但没跑”
  • 第三层挡不住”base64 绕正则”

三层叠起来,泄露概率压到接近 0。

总结

密钥永远不该出现在 git 历史里。一旦提交,即使删了,还在 git log,得用 git filter-branch 或 BFG Repo-Cleaner 彻底清,并立即轮换密钥。

三道防线三句话:

  1. 构建时:密钥从环境变量读,不给默认值
  2. 运行时:空 key 立即报错
  3. 提交时:pre-commit + CI + 人工复查

代价:多写 20 行代码,多配 1 个 .env.local,多加 1 个 pre-commit hook。比泄露后的损失(密钥轮换 + 事故复盘 + 可能的账单),值。

引用链接

[1]gitleaks: https://github.com/gitleaks/gitleaks

[2]truffleHog: https://github.com/trufflesecurity/trufflehog


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:后端一二事 一二 一二《API key 泄露进 git 的三道防线》

评论:0   参与:  0