阻止您的 AI 代理泄露 API 密钥、私钥和 PII

发布: (2026年2月15日 GMT+8 15:39)
9 分钟阅读
原文: Dev.to

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]
IPv4192.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_keysecretpasswordtoken,后跟 := 以及 20+ 字符的值。键名会保留在输出中,以便您知道 哪个 密钥被编辑。

区块链 / 加密密钥

类型示例替换为
EVM 私钥0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80[PRIVATE_KEY]
Solana 私钥87‑88‑字符 base58 字符串[SOLANA_PRIVATE_KEY]
Bitcoin WIF 密钥5KL 开头 + 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 赋值的一部分)时,算法按以下步骤执行:

  1. 通过 matchAll() 运行所有 模式,收集每个匹配及其位置。
  2. 起始位置 排序,若起始位置相同则按 长度(从长到短)排序。
  3. 从左到右扫描:如果一个匹配与已接受的匹配重叠,则跳过该匹配。

结果:最长、最左侧的匹配获胜。实际使用中,这会产生最有用的输出——你会看到 [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 代理的开源信任与支付通道。如果觉得有用,请给仓库加星。)

0 浏览
Back to Blog

相关文章

阅读更多 »