Skip to content

feat(pre-sign): approve-allowlist as security recommendation (closes #617) - #618

Merged
szhygulin merged 1 commit into
mainfrom
feat/allowlist-advisory
May 1, 2026
Merged

feat(pre-sign): approve-allowlist as security recommendation (closes #617)#618
szhygulin merged 1 commit into
mainfrom
feat/allowlist-advisory

Conversation

@szhygulin

Copy link
Copy Markdown
Collaborator

Closes #617.

Summary

  • New acknowledgedNonAllowlistedSpender?: boolean flag on UnsignedTx, flowed through the server-minted handle so the agent cannot fabricate it on a tx that didn't come through a prepare path that explicitly accepted the schema gate.
  • assertTransactionSafe: when approve(spender) targets a non-allowlisted spender AND the flag is stamped, skip ONLY the spender-allowlist refusal. Every other pre-sign defense (chainId, simulation, payload-hash, ABI-selector check, transfer-on-unknown-token) stays active.
  • prepare_curve_swap (steth_to_eth direction) takes the user's schema-enforced acknowledgeNonAllowlistedSpender: true. Without it, fail fast with a clear error so the agent surfaces the trade-off to the user before retry. With it, the approval tx carries the flag plus a ⚠ ADVISORY: spender NOT in allowlist description so the prepare receipt makes the user-side decision visible.

Mirrors the existing acknowledgeNonProtocolTarget (prepare_custom_call) and safeTxOrigin (prepare_safe_tx_*) patterns.

Test plan

  • Existing 34 pre-sign-check tests pass unchanged.
  • 2 new pre-sign-check tests: acked-bypass accepts; un-acked still refuses.
  • Existing curve-v1 happy-path test updated to pass the ack and assert the stamped flag + advisory description.
  • 2 new curve-v1 tests: steth_to_eth refuses without ack; eth_to_steth ignores the ack since no approval is built.
  • Full suite: 2,508 tests pass.
  • Live exercise: re-run the prepare_curve_swappreview_sendsend_transaction flow against a real Ledger to confirm the ack flag flows through end-to-end and the on-device clear-sign reads approve(<curve-pool>, <amount>).

🤖 Generated with Claude Code

…not a hard refusal

The pre-sign approve-allowlist (Aave Pool, Compound Comet, Morpho Blue,
Lido Queue, EigenLayer, Uniswap NPM, Uniswap SwapRouter02, LiFi Diamond)
hard-refused at preview/send time for any other spender. This blocked
legitimate flows like prepare_curve_swap (steth_to_eth), whose approval
target — the canonical Curve stETH/ETH pool 0xDC24316b9AE028F1497c275EB9192a3Ea0f67022 —
sits outside the curated set despite being a 5+ year immutable contract.

Mirror the existing `acknowledgeNonProtocolTarget` pattern:

- New optional `acknowledgedNonAllowlistedSpender?: boolean` on UnsignedTx,
  flowed through the server-minted handle (agent-fabrication-resistant).
- assertTransactionSafe: when an approve(spender) hits a non-allowlisted
  spender AND the flag is stamped, skip ONLY the spender refusal — every
  other defense (chainId, simulation, payload-hash, ABI-selector check,
  transfer-on-unknown-token) stays active.
- prepare_curve_swap (steth_to_eth) requires the user-passed
  `acknowledgeNonAllowlistedSpender: true` schema gate; without it, the
  prepare path fails fast with a clear error so the agent surfaces the
  trade-off to the user before re-trying. With it, the approval tx
  carries the flag plus a "⚠ ADVISORY: spender NOT in allowlist"
  description so the prepare receipt makes the user-side decision visible.

Tests:
- 2 new pre-sign-check cases (acked-bypass accepts; un-acked still refuses).
- 2 new curve-v1 cases (steth_to_eth refuses without ack; eth_to_steth
  ignores the ack since no approval is built); existing happy-path test
  updated to pass the ack and assert the stamped flag + advisory.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@szhygulin
szhygulin merged commit b01cf40 into main May 1, 2026
4 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators May 1, 2026
@szhygulin

Copy link
Copy Markdown
Collaborator Author

Skill-side companion piece filed: vaultpilot-security-skill#26 — Inv #11 expansion to add a skill-maintained approve-spender allowlist + ⚠ NON-CANONICAL SPENDER advisory. Mirrors the Inv #6 / Inv #1.a ground-truth-in-skill pattern. Closes the rogue-MCP-fabricates-the-ack-flag defense gap that this PR opens.

@szhygulin
szhygulin deleted the feat/allowlist-advisory branch May 19, 2026 04:24
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make approve-spender allowlist a security recommendation, not a hard refusal

1 participant