在上线之前保护您的代理钱包。
将代理支付投入生产的检查清单与正常的API集成不同。添加:一个明确的钱包类型选择,一个调整过的支出政策(而非默认),API和webhook密钥按规定周期轮换,每周审计日志审查,以及至少进行过一次演练的事件响应手册。没有这些,您将面临艰难的学习过程。
在您开始之前。
- 一个端到端的工作代理集成测试 - 请参见 add-payments-to-agent 和 test-without-real-money。
- 支出控制已配置 - 请参见支出控制(本指南假设已有政策)。
- 一个秘密管理器(AWS Secrets Manager、GCP Secret Manager、Vault、1Password 等) - .env 文件中的秘密不足。
- 一位明确识别的值班工程师,拥有钱包仪表板的管理员访问权限。
- 15分钟的专注时间。下面的清单不是理想的 - 一行一行地完成它。
运行预发布检查清单。
十一项内容。每一项都是一个有单一所有者的是/否问题。如果任何项目未被勾选,请不要上线 - 首先处理该项目。生产中遗漏项目的成本总是大于现在完成它的成本。
# Pre-launch security checklist for agent wallets.
[ ] Wallet type chosen with reasoned trade-offs (smart wallet vs EOA).
[ ] Spend permission set in the dashboard: an allowance per period + a per-transaction cap.
[ ] API keys scoped to the minimum the agent needs (read_wallet_metadata / pay_bills / receive_money).
[ ] All API keys stored in a secret manager (not env files committed to git).
[ ] Test keys and live keys cannot be swapped (boot-time prefix check in place).
[ ] Webhook secret rotated within the last 90 days (webhooks.rotateSecret).
[ ] Webhook URL pointed at production, not a tunnel.
[ ] Audit review scheduled; alerting in place for unusual events.
[ ] A spike of rejected payments triggers an alert (>5/hour from one agent).
[ ] Incident runbook exists, has been read by someone other than the author.
[ ] One person other than you knows how to revoke an API key in < 5 minutes.安排API密钥和Webhook密钥轮换。
季度是默认的轮换频率;在以下任何情况下立即轮换:怀疑泄漏、首席工程师离职、公司其他地方发生安全事件。双密钥窗口模式允许您在零停机时间内交换密钥:创建新密钥,部署到各处,验证,然后撤销旧密钥。
// One-time key rotation script. Run quarterly, on lead departure, on suspected leak.
import { createClient } from "@blockchain0x/node";
const client = createClient({ apiKey: process.env.BLOCKCHAIN0X_API_KEY! });
async function rotate() {
// Scope the new key to only what the agent needs.
const fresh = await client.apiKeys.create({
name: `prod-${new Date().toISOString().slice(0, 10)}`,
scopes: ["read_wallet_metadata", "pay_bills", "receive_money"],
});
console.log("NEW KEY:", fresh.secret); // Store in secret manager NOW.
// Wait until the new key is deployed and verified working, THEN:
// await client.apiKeys.revoke(OLD_KEY_ID); // (or apiKeys.rotate in one call)
}# One-time key rotation script. Run quarterly, on lead departure, on suspected leak.
from blockchain0x import Client
import datetime, os
client = Client() # reads BLOCKCHAIN0X_API_KEY
def rotate():
fresh = client.api_keys.create(body={
"name": f"prod-{datetime.date.today().isoformat()}",
"scopes": ["read_wallet_metadata", "pay_bills", "receive_money"],
})
print("NEW KEY:", fresh["secret"]) # Store in secret manager NOW.
# Wait until new key is deployed and verified, THEN:
# client.api_keys.revoke(OLD_KEY_ID) # (or api_keys.rotate in one call)Webhook 签名密钥通过仪表板以类似方式轮换 - 启用第二个密钥,重新部署处理程序以接受任一密钥,然后停用旧密钥。两者按季度进行,并设置日历提醒。
设置每周审核审查。
每周要关注三件事:新对手方(任何以前未见过的都值得进行 30 秒的合理性检查)、被拒绝的付款(支出权限发挥了作用 - 代理是否卡在某个地方?),以及非工作时间的付款(凌晨 3 点来自一个名义上只在工作时间运行的代理的付款是捕获注入攻击的早期信号)。
// Weekly audit query over the webhook events YOU persisted (payment.received /
// payment.sent). There is no transactions.list API - your own store is the log.
const since = Date.now() - 7 * 24 * 60 * 60 * 1000;
const events = await db.paymentEvents.findMany({ where: { receivedAt: { gte: since } } });
const newCounterparties = events.filter((e) => e.counterpartyFirstSeen);
const offHours = events.filter((e) => {
const h = new Date(e.receivedAt).getUTCHours();
return h < 5 || h > 22;
});
// Reconcile anything that looks off against the chain:
// const tx = await client.transactions.get(event.txHash);
console.log({ newCounterparties, offHours });from datetime import datetime, timedelta, timezone
# Query your own persisted webhook events - the SDK has transactions.get(id),
# not a list endpoint, so your event store is the audit log.
since = datetime.now(timezone.utc) - timedelta(days=7)
events = db.payment_events.where(received_at__gte=since)
new_counterparties = [e for e in events if e.counterparty_first_seen]
off_hours = [e for e in events if not (5 <= e.received_at.hour <= 22)]
# Reconcile against the chain when something looks off:
# tx = client.transactions.get(event.tx_hash)
print({"new_counterparties": new_counterparties, "off_hours": off_hours})编写(并演练)事件运行手册。
运行手册的好坏取决于它最近的测试情况。下面是模板 - 将其复制到您团队的 wiki 中,编辑以适应您的具体情况,并在下个季度安排 30 分钟的演练。计时;修复演练中揭示的任何缺失内容。
# Incident response runbook - Agent wallet compromise (suspected or confirmed)
## Trigger
Any of:
- Unrecognised counterparty receiving > $10 USDC.
- > 50 rejected payment attempts from one agent in an hour.
- Engineer reports they cannot account for a recent payment.
- A leaked API key surfaces in a public scan.
## Step 1 - Stop the bleeding (< 5 minutes)
- Revoke the suspect API key: dashboard, or apiKeys.revoke / apiKeys.rotate.
- Revoke the agent's spend permission in the dashboard (allowance to zero).
- A revoked key cannot move funds and a revoked permission authorizes nothing.
## Step 2 - Preserve evidence (< 15 minutes)
- Pull the last 24h from the dashboard activity log and your stored events.
- Note the agent's spend permission as it was at the time of the incident.
- Note the timestamps of any unrecognised payments and their txHash on Base
(fetch with transactions.get).
## Step 3 - Communicate (< 30 minutes)
- Inform the on-call lead and finance.
- If customer funds are affected, draft a notification template (do not send
until investigation is far enough along to be accurate).
## Step 4 - Root cause and remediation (24-72 hours)
- Determine: leaked key, compromised webhook secret, prompt-injection
bypass, integration bug, or other.
- Rotate every secret that could have been exposed.
- Tighten the spend permission (lower the allowance or per-transaction cap).
- File a post-mortem with timeline, RCA, and follow-ups.五个让团队在首次生产事件中陷入困境的事情。
将新代理视为“与旧代理完全相同”
每个代理都有自己的个人资料、自己的密钥和自己的支出政策。如果您在代理之间重用密钥“因为它们相似”,那么单个密钥的泄露会同时影响每个代理。创建一个新的代理个人资料只需一次API调用;每个代理的隔离是值得的,花费一分钟正确完成。
支出权限根据猜测而不是数据大小
根据猜测选择津贴和每笔交易的上限,结果会发生两种情况:太低,代理每天中午都会达到限制,而你调试“支付被拒绝”;太高,控制就成了戏剧。在第一周内,查看实际的每日支出并将津贴设置为2-3倍 - 不是1倍(太紧)也不是100倍(实际上是无限的)。这是一个仪表板更改,因此重新调整是便宜的。
Webhook签名秘密从未轮换
泄露webhook密钥的事件意味着攻击者可以伪造看起来像合法payment.received事件的webhook,这可能会欺骗你的处理程序交付从未支付的工作。按照与API密钥(每季度)相同的节奏旋转密钥(webhooks.rotateSecret)或在你怀疑泄露时随时旋转,并始终使用webhooks.verify与当前密钥验证交付。
没有人阅读的审计日志
审计日志只有在有人查看时才能捕捉到事情。大多数团队启用日志,却从不查看,并通过客户投诉发现问题。安排每周15分钟的审查:新对手方、被拒绝的支付、非工作时间的支付。成本微小;检测时间从几周减少到几天。
没有对事件运行手册的演练
一个从未被执行的运行手册是虚构的。选择一个季度日期,模拟一个密钥泄露场景,计算撤销和控制所需的时间。第一次演练总是会揭示缺失的东西(知道如何轮换的工程师正在休假,运行手册在过期的 Notion 链接后面)。在演练中发现这些问题总比在凌晨 3 点的真实事件中发现要好。
安全通行证后。
安全工作永远不会结束,但其余的操作堆栈受益于干净的基线。随着实际使用数据的积累,收紧支出控制,增强Webhook处理以应对负载,并验证代理身份,以便对手方信任您的公共资料。
完整参考见docs.blockchain0x.com。相关术语表:Coinbase智能钱包。产品表面:代理钱包。