Chain Signer

io.github.Kevthetech143由 GitHub 账号 Kevthetech143 发布v0.5.31更新于 Oct 24, 2026

Security suite for AI agents: flag drains, permit-phishing & risky actions before signing.

发布方自己的服务:Agent.chain.tokyo Address Contracts

已验证STDIO仅桌面金融安全与监控

概览

AI 生成的概览

在签名前筛查未签名的 EVM 交易、EIP-712 签名和拟执行的代理操作,识别盗取与授权钓鱼模式。

可以做什么
以 MCP 工具形式提供三个只读防护:preflight 解码未签名交易并标记盗取模式,例如无限授权、transferFrom 拉取、代理升级,以及隐藏在 multicall 或智能账户批量调用中的授权;inspect_signature 检查 EIP-712 类型化数据中的授权钓鱼和白送资产的 Seaport 订单;check_action 对拟执行的工具调用执行允许/禁止清单以及金额和收款方限制。此外还内置非托管钱包工具:create_wallet、get_balance、send、call_contract、swap 和 bridge。
适用场景
当代理需要签署或发送 EVM 交易,并希望在签名前对已知盗取和授权钓鱼模式做第一道检查时,值得添加。钱包工具是可选的,仅在需要代理自己持有密钥时才使用。
运行要求
通过 stdio 在本地运行,从 PyPI 安装并用 uvx 或 chain-signer-mcp 命令启动。无需账户,也不托管资产。可选环境变量 ETHERSCAN_API_KEY 仅在读取实时余额和广播交易时需要;防护功能可离线使用。
安装前请注意
钱包工具会在本地生成并使用私钥,持有该私钥的人即可控制资金,应存放在密钥管理器或加密密钥库中,而不是笔记或聊天里。send、swap、bridge 以及 x402 支付签名会在无提示的情况下转移资金并广播交易。防护仅为静态分析、只支持 EVM、不是模拟器,也不构成保证;高价值操作应配合模拟和人工复核。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Chain Signer,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

chain-signer

[PyPI] [Python] [License] [Release]

A security suite for AI agents — the seatbelt that catches the dangerous thing BEFORE it happens. Three guards, each callable on its own (and as MCP tools), pairing with any wallet or identity stack:

  • preflight(tx) — decode an unsigned transaction and flag drains before signing (unlimited/large approval, approve-all, token & NFT transferFrom, proxy upgrade, on-chain permit, on-chain Permit2 approve/permit/transferFrom, approvals hidden in multicall incl. Uniswap router batches and Multicall3 aggregate/aggregate3/aggregate3Value (the batch helper on every EVM chain), approvals wrapped in ERC-4337/smart-account execute/executeBatch, Gnosis Safe multiSend/execTransaction and DSProxy execute, drains routed through the Uniswap Universal Router (Permit2 permit/transferFrom commands incl. sub-plans), 1inch AggregationRouter v5 swap() with redirected output or zero slippage, 0x ExchangeProxy transformERC20() with zero slippage, EIP-7702 account delegation, will-revert).
  • inspect_typed_data(td) — catch permit-phishing in an EIP-712 message before the agent signs it (ERC-2612, Uniswap Permit2 incl. SignatureTransfer + witness variants, DAI-style permits) and Seaport orders that give assets away — zero consideration, proceeds routed to a third party, or hidden in a BulkOrder tree.
  • check_action(action, policy) — enforce allow/forbid + value/recipient limits before the agent acts.

All three fail safe and are guards, not guarantees. Also bundled: a non-custodial multi-chain wallet (burner, balance, send, swap) — the agent holds its own key and signs locally. No MetaMask, no account, no custody.

python
from chain_signer import assert_safeassert_safe(tx)   # raises if the tx is a drain/unlimited-approval/revert — review before signing

Install

pip install chain-signerexport ETHERSCAN_API_KEY=...   # for live balance reads + broadcast (Etherscan v2)

Bitcoin/Solana support is optional: pip install "chain-signer[all]".

Quickstart (10 seconds — offline, no key, no funds, no network)

pip install chain-signer
python
from chain_signer import preflightspender = "0x" + "22" * 20tx = {"to": "0x" + "33" * 20, "data": "0x095ea7b3" + spender[2:].rjust(64, "0") + "f" * 64, "value": 0}print(preflight(tx))   # ok=False — flags unlimited_approval before you'd ever sign

That's the wedge: the drain gets flagged before you'd ever sign it — no key, no funds, no network.

Bundled wallet (optional — the guards pair with any wallet)

python
from chain_signer import burner, send_etherfrom chain_signer.balance import get_balance
w = burner()                          # fresh throwaway wallet; the agent owns w.private_keyprint(w.address, get_balance(w))      # live on-chain balancesend_ether(w, "0x...recipient", 0.001)  # auto nonce+gas, signed locally, broadcast

Full runnable demos are in the repo: examples/agent_safety_demo.py (all three guards stop three real attacks) and examples/quickstart.py (wallet) — clone to run them, or just import as above.

Safety preflight (the wedge)

Before an agent signs, hand the unsigned tx to preflight() — it decodes the calldata and returns the risks, or use assert_safe() to hard-stop on a HIGH flag. Offline, no network, never raises.

python
from chain_signer import preflight, assert_safe
# an unlimited-allowance approve() to a spender — the classic drain setuptx = {"to": token, "data": "0x095ea7b3" + spender_padded + "f"*64, "value": 0}
report = preflight(tx)# {'decoded': {...}, 'ok': False,#  'risk_flags': [{'code': 'unlimited_approval', 'severity': 'HIGH',#                  'detail': 'approve() grants an effectively-unlimited allowance ...'}]}
assert_safe(tx)          # raises ValueError on a HIGH flag; pass force=True to overrideassert_safe(tx, sim=my_simulator)   # optional: also flag will-revert via your simulation hook

What it flags today: unlimited/large approval, increaseAllowance, setApprovalForAll, ERC-20 transferFrom + ERC-721/1155 safeTransferFrom (token & NFT drains), ERC-777 authorizeOperator/operatorSend (operator-grant + operator-pull drains), on-chain ERC-2612 and DAI-style permit, on-chain Permit2 approve/permit/transferFrom (single and batch — the dominant approval router: unlimited uint160 allowance + drain pull) plus Permit2 SignatureTransfer permit(Witness)TransferFrom (the one-shot signed-permit pull intent/filler protocols use), proxy upgradeTo/upgradeToAndCall, approvals hidden inside multicall (all router variants, nested) and Multicall3 aggregate/aggregate3/aggregate3Value (the canonical batch helper deployed at one address on every EVM chain), approvals wrapped in ERC-4337/smart-account execute/executeBatch, Gnosis Safe multiSend/execTransaction, or DSProxy execute(target,data)/execute(code,data) (decoded and recursed), drains routed through the Uniswap Universal Router (execute(commands,inputs) — Permit2 permit/transferFrom commands, batch and EXECUTE_SUB_PLAN), EIP-7702 account delegation (the "wallet upgrade" drainer), large native value, opaque calldata, malformed calls, and will-revert (with a sim hook). Honest limits (read these): this is STATIC analysis — it decodes calldata and matches known drain patterns. It is NOT a transaction simulator: it won't catch a novel/obfuscated drain it can't decode (those get a low-severity "unknown" flag, not a block), and simulation-based scanners go deeper there. Safety coverage is EVM-only today (no Solana/Bitcoin tx analysis). And it is not yet field-proven at scale. A first-line guard for known patterns — not a guarantee. Pair it with simulation + human review for high-value actions.

Signed-message inspector (the off-chain half)

A drain doesn't need a transaction. A dApp can ask the agent to sign an EIP-712 message — most dangerously a permit granting an unlimited token allowance, which preflight (a tx check) can't see. inspect_typed_data() catches it before the agent signs:

python
from chain_signer import inspect_typed_datareport = inspect_typed_data(typed_data)   # the EIP-712 object you're about to sign# ok=False, risk_flags=[{'code': 'unlimited_permit_signature', 'severity': 'HIGH', ...}]

Covers all three major permit shapes: ERC-2612, Uniswap Permit2 (PermitSingle/PermitBatch, plus SignatureTransfer and the witness variants intent protocols use), and DAI-style (allowed: true), plus Seaport marketplace orders that hand assets over for nothing — zero consideration, proceeds routed to a third party while your asset leaves, or the same giveaway buried in a BulkOrder merkle tree. Offline, never raises.

Guarded signer (screen + sign in one call)

inspect_typed_data only protects when the agent remembers to call it first — sign_typed_data alone will happily sign a permit-phishing message. guarded_sign_typed_data() composes the two so signing is screened by default: it inspects, then refuses to sign a HIGH-risk drain.

python
from chain_signer import guarded_sign_typed_data, SignatureBlockedsig = guarded_sign_typed_data(wallet, domain, types, message, "Permit")  # raises SignatureBlocked on a drain

On a clean message the signature is byte-identical to sign_typed_data; pass force=True to override.

Action-policy gate (inspect what the agent DOES)

Identity tells you who the agent is; it doesn't stop a bad action. check_action() enforces a policy on a proposed tool call before it runs — fail-safe (denies on unreadable input):

python
from chain_signer import check_actionpolicy = {"forbid_tools": ["bridge"], "max_value_wei": 10**18, "allow_recipients": [trusted_addr]}r = check_action({"tool": "send", "args": {"to": addr, "value_wei": 5*10**18}}, policy)# {'allowed': False, 'violations': [{'code': 'value_over_limit', ...}]}

All three guards are exposed as MCP tools (preflight, inspect_signature, check_action) — any agent runtime (Claude, Cursor, …) can call them directly, read-only, no key.

What's caught and what isn't — the honest threat-coverage map: docs/THREAT-COVERAGE.md.

What you get

  • preflight(tx) / assert_safe(tx) — decode an unsigned tx and flag drain patterns before signing.
  • inspect_typed_data(td) — flag permit-phishing in an EIP-712 message before the agent signs it.
  • guarded_sign_typed_data(w, domain, types, message, primary_type) — screen then sign; refuses a drain.
  • check_action(action, policy) — enforce allow/forbid + value/recipient limits before the agent acts.
  • burner() — a fresh wallet for a one-off task; discard it when done.
  • restore(key) — reload a wallet later from its exported private key (same key → same address).
  • send_ether(w, to, amount) — send in ETH (not wei); nonce, gas, and broadcast handled for you.
  • get_balance(w) — live balance from the chain (Etherscan v2 indexer, not a flaky public RPC).
  • swap(...) — token swaps via 0x/Paraswap.
  • Optional Solana + Bitcoin wallets via the [all] extra.

Non-custodial guarantee

The private key is generated/loaded locally, used only to sign, and never logged, returned, or stored by this library. You hold the key; we never touch your funds. That is the whole design.

Handling the key (read this)

w.private_key is the keys to the wallet. Treat it like a password:

  • NEVER log it, print it in production, or write it into notes/memory/chat. Anyone who has it controls the funds.
  • For a burner holding a few dollars this is low-stakes by design — but the rule still holds.
  • To reuse a wallet later, store the key in a secret manager / env var, then restore(key).
  • Better: export_encrypted(w, password) gives a password-protected keystore dict to store at rest; load_encrypted(keystore, password) brings the wallet back. Never store the raw key if you can store the keystore.

Signing idiom (note for web3.py users)

The wallet does not expose sign_transaction / sign_message methods. Signing is done by function helpers you pass the wallet to — e.g. send_ether(w, to, amount) signs and broadcasts, and sign_message(w, "text") returns an EIP-191 signature for auth / sign-in flows (recoverable via eth_account Account.recover_message).

CLI on PATH

pip install may warn that the chain-signer script dir isn't on your PATH. The library works regardless; to use the CLI directly, add that dir to PATH or run python -m chain_signer ....

Tool surface (for any AI / MCP / CLI)

chain_signer.mcp_server exposes list_tools() and call_tool(name, arguments). CLI:

python -m chain_signer listpython -m chain_signer call create_wallet '{"chain":"evm"}'

Responsible use

General-purpose, non-custodial tooling. You are responsible for using it within the laws and terms of service that apply to you. Not intended or marketed for any restricted or prohibited trading in your jurisdiction.

Notes

  • Balances/broadcast use the Etherscan v2 indexer (authoritative), never a free public RPC.
  • Low-level building blocks (tx.send, call_contract, explicit nonce/gas) remain available for advanced use.

Pay an x402 API in one call

python
from chain_signer import burner, sign_x402_paymentw = burner()payload = sign_x402_payment(w, token=USDC, to=PAY_TO, value=1000, valid_before=EXPIRES, chain_id=8453)# -> {"signature", "authorization"} ready for the x402 payment header. Signed locally, no prompt.

Builds + signs the EIP-3009 authorization x402 expects (the "exact" scheme). Your agent pays a paid API by itself — no password prompt, no signup, no custody.

Sign typed data (EIP-712) — for agent payments / x402

python
from chain_signer import burner, sign_typed_dataw = burner()sig = sign_typed_data(w, domain, types, message)  # EIP-712; for x402 / EIP-3009 authorizations

Your agent can authorize a payment by signing typed data locally — no password prompt, no signup.

Run as an MCP server

chain-signer is also a Model Context Protocol (MCP) server, so MCP-aware agents can use it directly:

pip install chain-signerchain-signer-mcp          # speaks MCP over stdio (JSON-RPC 2.0)

Exposes 9 tools. The three security guards (the wedge): preflight, inspect_signature, check_action. Plus the non-custodial wallet: create_wallet, get_balance, send, call_contract, swap, bridge.

Wire it into any MCP client (Claude Desktop, Cursor, etc.) by adding it to the client's mcpServers config:

json
{  "mcpServers": {    "chain-signer": {      "command": "chain-signer-mcp",      "env": { "ETHERSCAN_API_KEY": "your-key-for-live-balance-and-broadcast" }    }  }}

That's all — the agent can now screen every tx, signature, and action through the guards before it acts, and (optionally) hold its own wallet to read balances, send, and swap as native tools. (ETHERSCAN_API_KEY is optional; needed only for live balance reads and broadcasting.)

来源:README.md,提交 bc4f1f2

工具

0
SourceWeft 尚未在沙箱中启动过该软件包,因此其工具未知。

版本历史

1
  1. v0.5.31最新Sep 16, 2026

评分

已满足适用检查项的 50%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分

    请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。

  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分

其他 Chain 集成