配置 Codex 前先做 API Key 泄露自检:.env、.gitignore 与 LinkAGI 安全接入

复现结果:分别扫描两份 JavaScript 示例,API Key 硬编码文件命中 1 处;环境变量写法在当前三类规则下命中 0 处。本文给出浏览器工具、Python 命令行版、测试结果与修复清单。

在线工具:LinkAGI Key Guard

https://docs.linktoagi.com/tools/key-guard/

LinkAGI API 服务地址:https://api.linktoagi.com

文章封面

1. 问题复现:代码能跑通,Key 也进入了仓库

给 Codex、Claude Code、Gemini CLI 或 OpenAI-compatible SDK 配置接口时,最直观的写法通常如下:

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "sk-demo_this_is_not_a_real_key_20260721",
  baseURL: "https://api.linktoagi.com/v1"
});

请求可能正常,但 apiKey 已经成为源文件的一部分。随后执行 git add .、把项目上传到 GitHub,或把代码作为排错材料发到群里,都可能扩大凭据暴露范围。

仅在最新版本里删除这一行并不等于旧 Key 已经安全。Git 历史、CI 日志、构建产物和其他人的本地副本里仍可能保留原值。更可靠的原则是:源码只读取环境变量,真实 Key 只保存在受控的配置环境中。

2. 扫描器检查什么

网页端和 Python 命令行端使用相同的检查思路:

  • 匹配 sk- 开头的疑似 API Key;
  • 匹配硬编码的 Bearer Token;
  • 匹配 API_KEYTOKENSECRET 等敏感变量的字符串赋值;
  • process.env.*os.getenv() 等环境变量引用不会触发硬编码规则,但同一行若还存在 sk- 硬编码兜底仍会命中;
  • 输出时自动脱敏,只显示字符串头尾;
  • 网页端在浏览器本地处理,不上传粘贴文本,也不发送接口请求。

需要说明:正则快速检查无法代替完整安全审计。它的价值是把最常见的硬编码问题放到提交前,尽早暴露、尽早修复。

3. 真实命令行测试

下载 LinkAGI Key Guard 命令行版,解压后进入 tool 目录,先运行单元测试:

python3 -m unittest test_key_guard.py

本次实际运行结果为 3 项测试通过,覆盖硬编码、纯环境变量和“环境变量后带硬编码兜底”。随后扫描硬编码示例:

python3 linkagi_key_guard.py demo/leaky.js

输出:

LinkAGI Key Guard|已扫描 1 个文本文件
发现 1 处疑似硬编码:
  [!] leaky.js:2  sk- 格式 Key  sk-dem••••••••••••••••0721
建议:改用环境变量,并确认 .env 已被 Git 忽略且未被索引跟踪。

此时退出码为 1。扫描器输出的是脱敏片段,不会在终端里再次暴露完整字符串。

根据本次实测输出排版的命令行复查

把示例改为:

const apiKey = process.env.LINKAGI_API_KEY;
const baseURL = process.env.LINKAGI_BASE_URL;

再次运行:

python3 linkagi_key_guard.py demo/safe.js

结果:

LinkAGI Key Guard|已扫描 1 个文本文件
[OK] 没有发现明显硬编码。请继续确认 .env 与历史 Git 提交。

退出码恢复为 0。为了验证示例配置,我还执行了:

git -C demo check-ignore -v .env

Git 正确显示 .env.gitignore 规则命中。JavaScript 文件也通过 node --check app.js 语法检查。这里的“命中 0”仅代表当前规则没有找到问题,不覆盖 Git 历史、二进制文件、混淆后的 Key 或所有厂商格式。

4. 浏览器版的使用与可复查结果

打开 https://docs.linktoagi.com/tools/key-guard/ ,可以直接进行三步操作:

  1. 粘贴代码或配置;
  2. 点击“开始扫描”;
  3. 根据行号定位问题,并复制安全配置模板。

载入泄露示例后,页面显示“发现 1 处疑似硬编码”,同时给出类型、行号和脱敏值:

泄露示例命中 1 条

点击“换成安全写法”并重新扫描,当前规则命中 0 处:

环境变量写法扫描为 0

390px 移动端复查中,页面没有横向溢出,手机也能完成粘贴、扫描和复制模板。

移动端界面

5. LinkAGI 的推荐配置方式

LinkAGI 的控制台地址是:

https://api.linktoagi.com

SDK 中的 OpenAI-compatible Base URL 通常使用:

https://api.linktoagi.com/v1

建议在 .env 中保存:

LINKAGI_API_KEY=sk-your-key-here
LINKAGI_BASE_URL=https://api.linktoagi.com/v1

在 JavaScript 中读取:

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.LINKAGI_API_KEY,
  baseURL: process.env.LINKAGI_BASE_URL
});

Node.js 不会在所有版本、所有启动方式下自动读取 .env。Node 20.6 及以上可以显式运行:

node --env-file=.env app.js

也可以使用 dotenv,或在 shell / 部署平台中直接设置同名环境变量。Codex、Claude Code、Gemini CLI 的变量名和配置入口并不完全相同,应按 LinkAGI 文档中的对应工具页面填写;上面的代码只演示 JavaScript SDK。

并在 .gitignore 中加入:

.env
.env.*
!.env.example

完整链路如下:

.env 到 API 的安全配置链路

仅新增 .gitignore 不会停止跟踪此前已经加入索引的文件。继续执行:

git check-ignore -v .env
git ls-files --cached -- .env

如果第二条命令有输出,应先撤销可能已经暴露的旧 Key,再运行 git rm --cached .env,确认暂存区后提交修复。.env 本身仍是明文,.gitignore 只负责防误提交;生产环境优先使用部署平台的 Secret / 密钥管理能力。

Python 同样应通过 os.environ 读取变量。开发、测试和生产环境建议使用不同 Key,不同项目也最好分开创建,便于单独撤销和查看使用情况。

6. 已经误传到 GitHub,应该怎么处理

按下面顺序执行:

  1. 先撤销旧 Key。 不要先忙着改历史,服务端禁用才是最快的风险阻断。
  2. 创建新 Key。 改成环境变量读取,不要把新值再次写入源码。
  3. 检查调用记录。 查看是否出现异常请求或余额变化。
  4. 检查扩散位置。 包括 Git 历史、Fork、CI/CD 日志、构建产物、聊天附件。
  5. 按需清理历史。 对已公开的仓库,即使清理历史也不能假设所有副本都消失。

公开出现过的 Key 应直接按已经泄露处理。

7. 适合加入开发流程的三个检查点

7.1 创建 Key 后

先确定变量名、保存位置和忽略规则,再配置工具或应用代码。

7.2 提交代码前

运行 Key Guard,再查看:

git diff --cached

重点看临时调试代码、配置样例和日志语句。

7.3 仓库公开或发布教程前

私有仓库转公开、制作模板或上传压缩包前,用命令行版扫描目录。Git 仓库内会检查已跟踪文件和未被忽略的新文件;正确忽略的 .env 不进入普通扫描,已经被跟踪的 .env 仍会被检查。截图也要检查终端和配置页是否露出完整 Key。

8. 关于 LinkAGI

LinkAGI 提供面向常用 AI 开发工具的多模型 API 服务:

  • 控制台与实时价格:https://api.linktoagi.com
  • 接入文档:https://docs.linktoagi.com
  • 客服支持:文档内客服入口

模型与价格以控制台实时页面为准。

本文的最终行动只有一个:打开 LinkAGI Key Guard,把准备提交、分享或公开的代码先扫一遍。

https://docs.linktoagi.com/tools/key-guard/

先把最容易发生的泄露挡在提交之前,再去创建和配置新的 LinkAGI API Key。

更多推荐