阻止您的 AI 代理泄露 API 密钥、私钥和 PII
Source: Dev.to
Overview
你的 AI 代理会生成文本。这些文本有时会包含机密信息。
- 也许 LLM 从其训练数据中幻觉出一个 AWS 密钥。
- 也许某个工具在其输出中返回了数据库凭证。
- 也许代理正在汇总一份包含用户的社会安全号码、电子邮件或加密钱包私钥的文档。
如果这些输出到达最终用户——更糟的是,被记录到第三方服务——就会导致数据泄露。
本文展示了如何在文本离开系统之前,使用 Agntor SDK 中的 redact() 函数自动剥离任何敏感数据。该 SDK 提供了 17 种内置模式,覆盖个人身份信息、云密钥以及区块链特定密钥。
安装
npm install @agntor/sdk
基本用法
import { redact } from "@agntor/sdk";
const input = `
Here are the credentials:
AWS Key: AKIA1234567890ABCDEF
Email: admin@internal-corp.com
Server: 192.168.1.100
`;
const { redacted, findings } = redact(input, {});
console.log(redacted);
// Here are the credentials:
// AWS Key: [AWS_KEY]
// Email: [EMAIL]
// Server: [IP_ADDRESS]
console.log(findings);
// [
// { type: "aws_access_key", span: [42, 62] },
// { type: "email", span: [72, 95] },
// { type: "ipv4", span: [106,119] }
// ]
零配置。空策略 {} 会启用所有 17 种内置模式。
捕获内容
标准个人身份信息
| 类型 | 示例 | 替换为 |
|---|---|---|
| 电子邮件 | user@example.com | [EMAIL] |
| 电话(美国) | +1 (555) 123-4567 | [PHONE] |
| 社会安全号 | 123-45-6789 | [SSN] |
| 信用卡 | 4111 1111 1111 1111 | [CREDIT_CARD] |
| 街道地址 | 123 Main Street | [ADDRESS] |
| IPv4 | 192.168.1.1 | [IP_ADDRESS] |
云密钥
| 类型 | 示例 | 替换为 |
|---|---|---|
| AWS 访问密钥 | AKIA1234567890ABCDEF | [AWS_KEY] |
| Bearer 令牌 | Bearer eyJhbGciOiJI... | Bearer [REDACTED] |
| API 密钥/密钥 | api_key: "sk-abc123..." | api_key: [REDACTED] |
API‑key 模式很智能——它匹配 api_key、secret、password 和 token,后跟 : 或 = 以及 20+ 字符的值。键名会保留在输出中,以便您知道 哪个 密钥被编辑。
区块链 / 加密密钥
| 类型 | 示例 | 替换为 |
|---|---|---|
| EVM 私钥 | 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 | [PRIVATE_KEY] |
| Solana 私钥 | 87‑88‑字符 base58 字符串 | [SOLANA_PRIVATE_KEY] |
| Bitcoin WIF 密钥 | 以 5、K 或 L 开头 + 50‑51 个 base58 字符 | [BTC_PRIVATE_KEY] |
| BIP‑39 助记词(12) | abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about | [MNEMONIC_12] |
| BIP‑39 助记词(24) | 24‑词种子短语 | [MNEMONIC_24] |
| Keystore JSON 密文 | "ciphertext": "a1b2c3..." | "ciphertext": "[REDACTED_KEYSTORE]" |
| HD 派生路径 | m/44'/60'/0'/0/0 | [HD_PATH] |
实际示例:加密代理输出
import { redact } from "@agntor/sdk";
const agentOutput = `
I've set up your wallet. Here are the details:
Address: 0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18
Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
Recovery Phrase: abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
Derivation Path: m/44'/60'/0'/0/0
`;
const { redacted } = redact(agentOutput, {});
console.log(redacted);
// I've set up your wallet. Here are the details:
// Address: 0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18
// Private Key: [PRIVATE_KEY]
// Recovery Phrase: [MNEMONIC_12]
// Derivation Path: [HD_PATH]
Note: 公共钱包地址(42 个十六进制字符)未被脱敏——只有私钥(64 个十六进制字符)会被脱敏。正则表达式专门匹配 64 位十六进制字符的字符串,这正是 EVM 私钥的长度。
自定义模式
添加您自己的针对特定领域的机密模式:
const { redacted } = redact(agentOutput, {
redactionPatterns: [
{
type: "internal_endpoint",
regex: /https?:\/\/internal\.[a-z]+\.corp\/[^\s]*/gi,
replacement: "[INTERNAL_URL]",
},
{
type: "jwt_token",
regex: /eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
replacement: "[JWT]",
},
],
});
自定义模式会与默认模式合并,因此您既保留所有 17 条内置模式,又加入了自己的补充。
如何处理重叠匹配
当两个模式匹配到重叠的文本(例如,一个十六进制字符串既可能是私钥,又可能是 API‑key 赋值的一部分)时,算法按以下步骤执行:
- 通过
matchAll()运行所有 模式,收集每个匹配及其位置。 - 按 起始位置 排序,若起始位置相同则按 长度(从长到短)排序。
- 从左到右扫描:如果一个匹配与已接受的匹配重叠,则跳过该匹配。
结果:最长、最左侧的匹配获胜。实际使用中,这会产生最有用的输出——你会看到 [PRIVATE_KEY],而不是部分被遮蔽的字符串。
Express 中间件示例
import express from "express";
import { redact } from "@agntor/sdk";
const app = express();
// Redaction middleware — intercepts JSON responses
app.use((req, res, next) => {
const originalJson = res.json.bind(res);
res.json = (body: unknown) => {
const bodyStr = JSON.stringify(body);
const { redacted, findings } = redact(bodyStr, {});
if (findings.length > 0) {
console.warn(
`Redacted ${findings.length} sensitive items:`,
findings.map((f) => f.type)
);
}
// Send the redacted payload
return originalJson(JSON.parse(redacted));
};
next();
});
// ... define routes as usual
app.listen(3000, () => console.log("Server listening on :3000"));
该中间件会序列化响应,删除所有机密信息,记录被移除的内容,然后将清理后的 JSON 返回给客户端。
要点
通过在你的 AI‑agent 流水线(或任何文本离开受信任边界的地方)中插入 redact(),可以自动防止 API 密钥、私钥以及个人身份信息的意外泄露。
.post("/api/agent", async (req, res) => {
const llmOutput = await callYourLLM(req.body.prompt);
// Even if the LLM leaks secrets, they get stripped here
res.json({ result: llmOutput });
});
与输入守卫结合
Redaction 负责输出端的处理。对于输入端,可以将其与 guard() 结合使用:
import { guard, redact } from "@agntor/sdk";
async function processAgentRequest(userInput: string) {
// 1. Guard the input
const guardResult = await guard(userInput, {});
if (guardResult.classification === "block") {
throw new Error(
"Input rejected: " + guardResult.violation_types.join(", ")
);
}
// 2. Process with your LLM
const output = await callYourLLM(userInput);
// 3. Redact the output
const { redacted } = redact(output, {});
return redacted;
}
或者使用 wrapAgentTool(),它可以在一次调用中完成 guard + redact + SSRF 检查:
import { wrapAgentTool } from "@agntor/sdk";
const safeTool = wrapAgentTool(myTool, {
policy: {},
});
// Inputs are redacted and guarded, then the tool executes
const result = await safeTool("https://api.example.com/data");
性能
Redaction 完全在进程内使用正则表达式运行。没有网络调用、没有 LLM 推理,也没有外部依赖(除 SDK 本身外)。
- 对于典型的代理输出(500–2000 字符),
redact()在 1 毫秒以下 完成。 - 即使在大型文档(100 KB 以上),也保持 10 毫秒以下。
您可以安全地在每个响应上调用它,而不会产生可测量的延迟影响。
Limitations
- False positives on hex strings – 64字符的十六进制哈希(例如 SHA‑256 摘要)会匹配私钥模式。如果你的代理经常输出非机密的十六进制哈希,请相应调整模式。
- Mnemonic detection is greedy – 任意由 12 或 24 个小写单词(每个 3–8 个字符)组成的序列都会匹配。这在极少数情况下可能会标记合法的英文文本。
- No semantic understanding – 过滤仅基于模式,无法区分真实的 AWS 密钥和外观相似的字符串。这种取舍倾向于产生误报(更安全),而非漏报(更危险)。
源代码
所有代码均为开源(MIT):
如果你正在构建生成文本的代理——尤其是与 API、数据库或区块链交互的代理——请添加输出脱敏。这只需一行代码即可防止整类数据泄露。
(Agntor 是一个面向 AI 代理的开源信任与支付通道。如果觉得有用,请给仓库加星。)