高熵凭据检测:不只匹配已知密钥,也检查没有固定格式的随机凭据。
High-entropy credential detection — beyond known key formats.
简体中文 · English
高熵检测 ·
本地全开 ·
验证 ·
接入 ·
安全边界
凭据不一定以 sk- 开头。一个内部服务令牌,可能只是代码、配置、日志或工具结果里的一串随机字符。
Cosy 是面向程序员的 LLM 凭据脱敏网关,核心是高熵凭据检测(High-entropy credential detection)。 它不仅匹配已知密钥格式,还对符合条件的文本块进行统计评分,寻找随机形态的凭据候选,不要求厂商前缀,也不要求 password= 这样的赋值标签。
全部检测器启用时,高熵检测与结构化检测、Gitleaks 兼容密钥规则协同工作:命中内容在转发前替换为可逆占位符,并在普通响应、受支持的 SSE 流和工具调用参数中还原已知、未被修改的占位符。高熵检测对应配置开关 H。
面向程序员的本地优先用法:把 Cosy 跑在本机,让受支持的 LLM 调用经过它。 下方示例统一使用 /$https://…,启用全部检测器。
保护范围: 检查经过网关的 JSON 文本,并替换命中的内容,不是拦截主机全部流量。检测仍可能漏检;上游认证凭据仍会转发。部署到云端时,云端网关会先接收到原始请求。安全边界 →
固定格式规则检查文本是否匹配已配置的模式;高熵检测还会检查:符合条件的文本块,是否显著不像普通英文文本。 因此,即使没有已知厂商前缀,也没有凭据赋值标签,随机形态的凭据仍多了一条被识别的路径。
| 检测层 | 带来的覆盖 |
|---|---|
| 已知格式与结构化规则 | 识别受支持的厂商密钥特征、凭据赋值形式和结构化个人信息。 |
| 高熵凭据检测 / High-entropy credential detection | 对超过 8 个字符的 ASCII 字母数字块进行长度感知的英文二元字符交叉熵评分,并检查字符多样性;排除纯数字块。 |
全开:HPSIBEG |
组合以上检测路径。标志位留空即启用全部检测器,不是“只开高熵检测”。 |
增加的是检测路径,不是“随机串必然是凭据”或“所有凭据都能拦截”的保证。 实现与校准说明:worker.js、熵检测方法。
这是机制示意,不是实测录屏。示例凭据为合成字符串,占位符经过缩写,不含真实凭据。
| 阶段 | 示意文本 |
|---|---|
| 应用发出 | 检查这个值: q7X9v2L5m8N4r6T1w3Y0z5A8b2C9d7F4 |
| 该值被检测命中后,上游收到 | 检查这个值: {{Redact:…}} |
| 模型原样返回占位符 | 这个值是 {{Redact:…}} |
| Cosy 为应用还原 | 这个值是 q7X9v2L5m8N4r6T1w3Y0z5A8b2C9d7F4 |
只有模型原样保留已知占位符时,原值才能恢复。真实占位符包含 64 个字符的 SHA-256 摘要。Cosy 也会还原工具参数,但不会执行工具,也不负责授权工具动作。完整往返机制 →
一次完整的脱敏与还原往返
这是往返机制示意,使用合成数据;摘要与协议提示已缩略。只有当前请求中已知且未被改写的占位符才能还原。
安全卖点应该能检查。仓库提供一个纯本地、无需 API Key 的演示脚本,直接调用仓库导出的检测与脱敏函数:
node scripts/demo-high-entropy.mjs它会对同一个无标签的合成字符串,分别打印 PSIBEG(关闭高熵检测)、H(仅高熵检测)、空标志位(全部启用) 时的实际结果,并检查精确还原以及高熵检测已说明的排除条件。脚本不联网,不调用模型;结果只描述这些合成样例,不代表生产环境泄漏率。
仓库中更完整的回归与熵检测样本可这样运行:
npm test
npm run entropy-report项目已发布的校准记录中,30,000 个自然词拼接样本有 296 个(0.9867%)被判为高熵;随机 hex/base62 样本的召回率随长度提高。这是合成样本结果,不是生产泄漏率,也不是本次 README 更新独立复测出的基准成绩。校准方法 · 高熵检测:证据、验证方法与限制
需要 Node.js 20+、Git 和终端。网关无需安装运行时依赖。HTTP 示例使用 Bash 和 curl 7.76+。
git clone https://github.com/CassiopeiaCode/CosyRedactGateway.git
cd CosyRedactGateway
npm start本地开发适配器默认监听 http://127.0.0.1:8787。此用法保持绑定本机回环地址。
另开一个终端,进入同一个仓库目录:
curl --fail --silent --show-error http://127.0.0.1:8787/healthz
node scripts/demo-high-entropy.mjs第一条检查服务可用性;第二条离线检查合成检测样例。都不需要 API Key。
通过日常的密钥管理方式在环境中导出 OPENAI_API_KEY,并将 OPENAI_MODEL 导出为账户可用的模型。这会真实调用上游,可能产生费用。
: "${OPENAI_API_KEY:?Set OPENAI_API_KEY in this shell first}"
: "${OPENAI_MODEL:?Set OPENAI_MODEL to a model available to your account}"
node --input-type=module -e '
const payload = {
model: process.env.OPENAI_MODEL,
messages: [{
role: "user",
content: "请原样返回这个值: q7X9v2L5m8N4r6T1w3Y0z5A8b2C9d7F4"
}],
stream: true
};
process.stdout.write(JSON.stringify(payload));
' | curl --fail-with-body --no-buffer \
-H 'content-type: application/json' \
-H "authorization: Bearer ${OPENAI_API_KEY}" \
--data-binary @- \
'http://127.0.0.1:8787/$https://api.openai.com/v1/chat/completions'$ 前的标志位留空,等于启用 HPSIBEG:包括高熵检测在内的全部检测器。 模型原样返回被检测值的占位符时,应用会收到还原后的原值;模型输出本身不保证确定。Shell 中的路由 URL 要使用单引号,避免 $ 被展开。
提供商认证头仍会转发到指定上游。此示例检验的是请求正文内容的脱敏,不是隐藏用于认证该 API 调用的密钥。
保留上游 API Key、模型和请求结构,把目标地址改成 Cosy 路由。客户端需要完整保留嵌入的上游 URL,并正确追加 API 路径。
所有下方路由均启用全部检测器,包括高熵检测。客户端必须真正把相关请求经过此网关。
在应用环境中安装 SDK,而不是给网关增加依赖:python -m pip install openai。在环境中导出 OPENAI_API_KEY、OPENAI_MODEL 并启动本地网关后:
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["OPENAI_API_KEY"],
base_url="http://127.0.0.1:8787/$https://api.openai.com/v1",
)
response = client.responses.create(
model=os.environ["OPENAI_MODEL"],
input="请原样返回这个值: q7X9v2L5m8N4r6T1w3Y0z5A8b2C9d7F4",
)
print(response.output_text)预期路由路径以 $https://api.openai.com/v1/responses 结尾;Chat Completions 使用相同的 Base URL。SDK 配置参考
Anthropic JavaScript SDK
在应用中安装 @anthropic-ai/sdk。设置 ANTHROPIC_API_KEY,并将 ANTHROPIC_MODEL 设置为可用模型,然后将以下内容保存为 .mjs 文件运行:
import Anthropic from '@anthropic-ai/sdk';
const apiKey = process.env.ANTHROPIC_API_KEY;
const model = process.env.ANTHROPIC_MODEL;
if (!apiKey || !model) {
throw new Error('Set ANTHROPIC_API_KEY and ANTHROPIC_MODEL first.');
}
const client = new Anthropic({
apiKey,
baseURL: 'http://127.0.0.1:8787/$https://api.anthropic.com',
});
const message = await client.messages.create({
model,
max_tokens: 128,
messages: [{
role: 'user',
content: '请原样返回这个值: q7X9v2L5m8N4r6T1w3Y0z5A8b2C9d7F4',
}],
});
console.log(message.content);SDK 会追加 /v1/messages;不要在这个 Base URL 后再添加 /v1。SDK 源码与配置
IDE 助手、命令行工具与自定义 HTTP 客户端
对于支持自定义 API Base URL 的工具,先确认它实际使用的协议:
| API 家族 | Base URL 示例 |
|---|---|
追加 /chat/completions 或 /responses 的 OpenAI 风格客户端 |
http://127.0.0.1:8787/$https://api.openai.com/v1 |
追加 /v1/messages 的 Anthropic 风格客户端 |
http://127.0.0.1:8787/$https://api.anthropic.com |
| 自定义 HTTP 客户端 | 像 curl 示例一样,把完整上游端点放在 $ 之后。 |
支持协议,不等于完成了某个产品的兼容认证。 Cursor、Claude Code、Codex 等工具的版本、认证模式、URL 处理方式,以及请求实际发起的位置都可能不同。这里不作特定版本的端到端兼容承诺。接入敏感工作前,请用合成数据核对实际请求路径。远程执行的客户端无法访问你电脑上的 127.0.0.1。
| 设计选择 | 对现有技术栈意味着什么 |
|---|---|
| 单文件核心 | 审阅或部署 worker.js;核心使用 Web Fetch、Web Streams 和 Web Crypto API。 |
| 协议透传 | 保留上游请求结构,而不是在不同 API 家族之间转换。 |
| 请求级映射 | 在当前请求中还原原值,无需持久化映射数据库。 |
| 理解流式边界 | 处理受支持的文本和工具参数增量,包括跨 SSE 事件、跨 HTTP chunk 的占位符。 |
| 显式检测策略 | 通过 URL 字母开关选择结构化检测、高熵检测与 Gitleaks 兼容规则。 |
| Apache-2.0 许可证 | 阅读许可证与第三方声明,把隐私层留在自己的技术栈中。 |
https://<cosy-host>/<flags>$<full-upstream-url>
开关部分留空,即启用全部检测器。 HPSIBEG 是显式全开写法。未知字母返回 HTTP 400,而不是静默改变策略。
| 开关 | 检测器 | 范围 |
|---|---|---|
H |
高熵凭据检测(High-entropy credential detection) | 长度超过 8 的 ASCII 字母数字块;使用与长度相关的二元字符评分,排除纯数字块。 |
P |
电话号码 | 中国大陆手机号与国际 +… 格式。 |
S |
长 sk- 密钥 |
sk- 后至少 60 位 ASCII 字母数字;不代表覆盖所有服务商的密钥格式。 |
I |
中国居民身份证 | 对候选身份证号码进行校验码验证。 |
B |
银行卡候选号码 | 13–19 位数字并通过 Luhn 校验,包含常见分组形式。 |
E |
邮箱地址 | 匹配邮箱格式,例如 alice@example.com。 |
G |
Gitleaks 兼容规则 | 文档中的规则集包含 218 条 JavaScript 条目,支持关键词、secret groups、熵检查与允许列表。 |
按数据特点选择开关,再评估误报与漏报。校验码命中不证明账户或身份真实存在。G 是适合 serverless 的兼容实现,不承诺与 Gitleaks CLI 完全等价。检测器细节 →
| API 家族 | 请求处理 | 响应处理 |
|---|---|---|
| OpenAI Chat Completions | JSON 文本脱敏 + 用户消息 Notice | JSON;受支持的 SSE 文本与 tool/function 增量 |
| OpenAI Responses | 字符串或消息数组输入 + Notice | JSON;受支持的 SSE 文本与函数参数增量 |
| Anthropic Messages | 消息脱敏 + 用户消息 Notice | JSON;受支持的 SSE 文本与工具 partial-JSON 增量 |
| 其他 JSON 端点 | 通用字符串脱敏;仅在识别出受支持的请求家族时注入 Notice | 文本与 JSON 还原;不对任意流式 schema 作全面兼容承诺 |
Cosy 不会把 OpenAI 请求转换为 Anthropic 请求,反之亦然。带有非空、非 JSON 请求体的请求会返回 HTTP 415,而不是绕过脱敏直接转发。为避免破坏请求,部分控制字段、URL 和图像/音频载荷字段会跳过文本脱敏。
仓库文档列出的测试覆盖 75 字节占位符的每一个切分位置、单字节 HTTP 传输块、受支持的 SSE 格式、工具/推理增量,以及本地 HTTP 和 Node 适配器集成。实现见 worker.js,测试用例见 test/。
npm test
npm run entropy-report文档中的熵检测 fixture 将 30,000 个自然词拼接样本中的 296 个(0.9867%)判为高熵;随机 hex/base62 字符串的召回率随长度上升。这些是合成测试样本结果,不是真实业务隐私保证、吞吐性能基准或独立安全审计。方法与复现 →
展开动画:占位符跨 SSE 分段,也能还原
机制示意,非实测录屏。摘要与 SSE 封装经过缩略;演示的是已知占位符的缓冲与还原,不代表任意流式格式都已通过兼容性验证。
| 运行时 | 入口 | 使用方式 |
|---|---|---|
| Cloudflare Workers | worker.js |
Module Worker;无需应用构建步骤 |
| Deno | worker.js |
直接运行,或作为 Deno Deploy 入口 |
| Node.js 20+ | node-server.mjs |
本地开发适配器 |
Cloudflare Workers
配置好 Wrangler 与 Cloudflare 账号后,在仓库目录执行:
npm test
npx wrangler deploywrangler.toml 已指向 worker.js,也可以直接将文件上传为 Module Worker。请将上游允许列表配置为 Worker 变量;仅在本地 shell 中设置变量,并不会配置线上 Worker。
REDACT_ALLOWED_HOSTS=api.openai.com,api.anthropic.com
需要时加入自己的上游主机名。Wrangler 是部署工具,不是网关的运行时依赖。开放公网流量前,还需添加访问控制并阅读安全边界。
Deno
在可信环境中运行,并限制上游主机:
REDACT_ALLOWED_HOSTS=api.openai.com,api.anthropic.com \
deno run --allow-net --allow-env worker.js直接执行时会调用 Deno.serve(...) 并读取环境变量。同一模块也可作为 Deno Deploy 项目的入口;请在对应部署中配置环境变量与访问控制。
网关属于信任范围;上游不应获得已命中的敏感原文。 原始请求、服务商凭证和替换映射会存在于网关运行时。部署到托管环境意味着信任该宿主,不等于所有处理都留在本机。
| Cosy 会做什么 | 不作哪些保证 |
|---|---|
| 转发前替换命中的文本 | 发现全部敏感值,或保持所有任务的回答质量不变 |
| 替换映射仅在当前请求中存在,不持久化 | 密码学意义的擦除、请求匿名化,或跨请求还原 |
| 还原未被修改的已知响应占位符 | 找回模型改写或凭空生成的占位符 |
| 拒绝不受支持的非 JSON 请求体 | 检查图像/音频内容,或脱敏所有 URL、请求头和控制字段 |
| 过滤代理/浏览器身份相关请求头 | 隐藏上游凭证:Authorization 和 x-api-key 会按设计转发 |
对外开放部署前: 配置 REDACT_ALLOWED_HOSTS,保留私有上游阻断,并添加外部认证/访问控制。主机允许列表限制目标地址,不会认证调用者。检查周边组件的请求日志与留存策略;不要把内置主机名检查当作完整的网络出口或 SSRF 防护。
默认限制为每个请求体 16 MiB、每个请求最多 16,384 个不同原值替换。默认 CORS 为 *,它不是访问控制。Notice 可按需关闭,也可固定在会话开头以保持增长会话的前缀稳定。全部运行时配置 → · 现有安全策略 →
“凭据留在本地”是否等于“主机没有任何凭据出网”?
不等于。这表达的是本地部署下,对受检查正文中的命中凭据进行出网前替换的目标,不是整机零泄漏承诺。Authorization、x-api-key 等认证头会按设计发送给上游;跳过的字段、未命中的文本和绕过网关的流量不在这一承诺范围。云端 Worker 或远程 Deno 实例也不是你的本地主机。
这是加密,或者不可逆匿名化吗?
都不是。Cosy 用带运行时盐的哈希标识替换选定字符串,再用内存查找表反向恢复。周边提示词仍会发送给上游。哈希标识也不能消除所有推断与关联风险。
“请求级映射”究竟是什么意思?
原文到占位符的映射只属于当前请求及其响应流,结束后会被丢弃。盐按运行时/isolate 生成,不是每次请求生成;同一运行时内,相同原文可能产生相同占位符。旧请求中的占位符,只有在当前请求重新建立对应映射后才能还原。
现有工作流一定保持原样吗?
不一定。命中的文本会被替换;支持的用户消息会插入 Notice;部分请求头会被过滤;协议专用流式处理只覆盖已识别字段。需要原值参与的任务可能受影响,误报也可能移除有用上下文。先用合成样本测试自己的提示词和工具链。
可以使用内网或本地上游吗?
主机名规范化之后,默认会阻断字面形式的私有、回环和链路本地目标。仅在有意设计的可信私有部署中关闭 REDACT_BLOCK_PRIVATE_UPSTREAMS。允许列表和网络层出口限制仍然重要。路由与错误 →
欢迎贡献检测器回归用例、误报/漏报报告、可复现的客户端接入验证,以及 SSE 边界案例。提交 Issue 时,请说明运行时、协议、开关,以及合成或已脱敏的复现数据。不要附上真实凭证或私有提示词。提交修改前运行 npm test;安全问题报告请遵循 SECURITY.md。
路由、生命周期与运行时配置 · 熵检测校准 · 源码 · 测试 · 第三方声明
URL 外壳沿用 TransformVetter 的 /{config}${upstream-url} 约定;Cosy 不包含其协议转换或内容审核引擎。部分规则签名源自 Gitleaks,详见第三方声明。
感谢 Linux.do 社区的支持。本项目使用 Apache License 2.0。
代码交给 AI。凭据,不该跟着走。先在本地检查,再交给上游。