Back to skill

Security audit

Use Gateway

Security checks for vulnerabilities and agentic risk

Overview

The skill is a legitimate Circle Gateway integration, but its examples can sign and submit real USDC movements without built-in review steps and include a mainnet/testnet configuration mismatch.

Review this before installing if you plan to let an agent generate runnable payment code. Keep it on testnet until you add explicit confirmation screens, strict amount/address/domain validation, mainnet acknowledgments, and fixes for the Solana environment mismatch; protect Circle API keys and entity secrets as production signing authority.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
references/evm-to-evm.md:118
Finding
Financial transfer handlers omit mandatory confirmation and comprehensive input validation<![CDATA[ ## Vulnerability Details **File Locations**: - `references/deposit-evm.md:87-106` - `references/deposit-solana.md:66-80` - `references/evm-to-evm.md:118-164` - `references/evm-to-solana.md:187-289` - `references/solana-to-evm.md:245-294` - `references/solana-to-solana.md:291-371` - `references/transfer-evm-circle-wallet.md:179-214` **Vulnerability Type**: Missing transaction confirmation and insufficient validation of financial-operation parameters **Risk Level**: High ### Vulnerable Code A representative vulnerable transfer path appears in `references/evm-to-evm.md`: ```tsx const handleTransfer = async (input: EvmBurnIntentInput, network: NetworkType = "testnet") => { if (!evmAddress) return; const sourceChain = input.sourceChainConfig[network]; const destChain = input.destinationChainConfig[network]; if (!sourceChain || !destChain) return; try { setError(null); setStep("signing"); const recipient = (input.recipientAddress ?? evmAddress) as Hex; const transferAmount = parseUnits(input.transferAmountUsdc, 6); const burnIntent = { maxBlockHeight: maxUint64.toString(), maxFee: MAX_FEE.toString(), spec: { version: 1, sourceDomain: input.sourceChainConfig.domain, destinationDomain: input.destinationChainConfig.domain, sourceContract: evmAddressToBytes32(sourceChain.GatewayWallet as Hex), destinationContract: evmAddressToBytes32(destChain.GatewayMinter as Hex), sourceToken: evmAddressToBytes32(sourceChain.USDCAddress as Hex), destinationToken: evmAddressToBytes32(destChain.USDCAddress as Hex), sourceDepositor: evmAddressToBytes32(evmAddress), destinationRecipient: evmAddressToBytes32(recipient), sourceSigner: evmAddressToBytes32(evmAddress), destinationCaller: evmAddressToBytes32(zeroAddress), value: transferAmount.toString(), salt: randomHex32(), hookData: "0x" as Hex, }, }; cons ...[truncated 3684 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Introduce a mandatory confirmation state before any wallet signature, token approval, deposit, burn-intent submission, or mint transaction. 2. Display a trusted summary containing: - Token symbol and verified token contract or mint - Human-readable amount and base-unit amount - Maximum fee - Source network and domain - Destination network and domain - Source account - Final recipient account - Gateway Wallet and Gateway Minter addresses 3. Require a fresh, explicit confirmation after the summary is generated. Do not treat clicking an earlier navigation or form button as transfer confirmation. 4. Validate amounts with strict decimal syntax and reject zero, negative, excessive-precision, overflowed, or policy-exceeding values. 5. Validate EVM addresses with a canonical address validator and Solana addresses with `PublicKey`. For Solana recipients, verify whether the input is already a USDC token account before deriving an associated token account. 6. Resolve domain IDs, token addresses, and Gateway contracts exclusively from an allowlisted network configuration. Verify that all selected values belong to the same intended environment. 7. Require a separate mainnet acknowledgment and display a prominent warning for mainnet or transfers above the configured safety threshold. 8. Revalidate all values immediately before signing to prevent time-of-check/time-of-use changes in application state. 9. For developer-controlled wallets, require an authenticated approval workflow, transaction policy limits, destination allowlists where appropriate, and audit logging that excludes secrets and sensitive signing material. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/solana-to-evm.md:264
Finding
Solana-to-EVM mainnet transfers incorrectly embed devnet source contracts<![CDATA[ ## Vulnerability Details **File Location**: `references/solana-to-evm.md:264-266` **Vulnerability Type**: Cross-environment configuration mismatch **Risk Level**: Medium ### Vulnerable Code ```tsx sourceContract: solanaAddressToBytes32(solanaContracts.devnet!.GatewayWallet), destinationContract: evmAddressToBytes32(destChain.GatewayMinter as Hex), sourceToken: solanaAddressToBytes32(solanaContracts.devnet!.USDCAddress), ``` ### Technical Analysis The surrounding `handleTransfer` function accepts a runtime network parameter that may be either `"mainnet"` or `"testnet"`: ```tsx const handleTransfer = async ( input: SolBurnIntentInput, network: NetworkType = NETWORK ) => { ``` The destination EVM configuration and Gateway API endpoint are selected from that parameter, but the Solana source contract and USDC mint are always taken from `solanaContracts.devnet`. Consequently, selecting mainnet creates an internally inconsistent burn intent containing: - The Solana domain identifier - Devnet Gateway Wallet and USDC mint addresses - A mainnet destination configuration - Submission to the mainnet Gateway API endpoint The user is then asked to sign this malformed cross-environment intent. This violates the requirement to validate blockchain-specific values and use the configuration corresponding to the selected environment. ### Attack Path 1. An application exposes or programmatically selects `network = "mainnet"`. 2. The handler resolves the destination EVM chain from its mainnet configuration. 3. The handler nevertheless inserts the Solana devnet Gateway Wallet and devnet USDC mint into the source fields. 4. The connected Solana wallet signs the inconsistent burn intent. 5. The signed request is sent to the mainnet Circle Gateway endpoint. 6. The operation fails validation or behaves inconsistently with the user's stated mainnet transfer, potentially after the user has approved a confusing signing request. No evidence establishes that this mism ...[truncated 649 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Resolve the Solana source configuration once from the selected environment and use it consistently throughout intent construction: ```tsx const sourceConfig = solanaContracts[network === "mainnet" ? "mainnet" : "devnet"]; if (!sourceConfig) { throw new Error(`Missing Solana source configuration for ${network}`); } const burnIntent = { maxBlockHeight: MAX_UINT64, maxFee: MAX_FEE, spec: { version: 1, sourceDomain: solanaContracts.domain, destinationDomain: input.destinationChainConfig.domain, sourceContract: solanaAddressToBytes32(sourceConfig.GatewayWallet), destinationContract: evmAddressToBytes32(destChain.GatewayMinter as Hex), sourceToken: solanaAddressToBytes32(sourceConfig.USDCAddress), destinationToken: evmAddressToBytes32(destChain.USDCAddress as Hex), // Remaining fields... }, }; ``` Additionally: 1. Assert that the source configuration, destination configuration, and Gateway API endpoint all belong to the same environment. 2. Compare the connected Solana RPC genesis or cluster identity with the selected environment before requesting a signature. 3. Present the resolved source Gateway Wallet, USDC mint, destination chain, and recipient in the mandatory confirmation screen. 4. Add automated tests covering both testnet/devnet and mainnet paths, including assertions that no devnet address appears in a mainnet intent. 5. Fail closed on any missing or mixed-environment configuration rather than using non-null assertions. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (12)

Vague Triggers

Medium
Confidence
91% confidence
Finding
The trigger list contains broad terms such as 'Gateway', 'capital efficiency', and 'payment routing' that can match many unrelated user requests. In an agentic system, overbroad activation can route users into a high-risk financial skill unnecessarily, increasing the chance of unintended wallet, transfer, or contract guidance being surfaced in the wrong context.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- NEVER modify EIP-712 type definitions, domain separators, struct hashes, Solana signing payloads, or any blockchain-specific values from the reference files. Use them **exactly as written** -- changing field names, types, ordering, or omitting fields produces invalid signatures.
- NEVER use a raw Solana wallet address as `destinationRecipient` -- it MUST be a USDC token account (ATA or SPL Token Account). Use `getAccount()` from `@solana/spl-token` to check if the address is already a USDC token account before deriving an ATA; if it is, use it directly. Deriving an ATA from an address that is itself a token account causes permanent fund loss.
- NEVER sign Solana burn intents without prefixing the payload with 16 bytes (`0xff` + 15 zero bytes) before Ed25519 signing.
- ALWAYS require explicit user confirmation of destination, amount, source/destination network, and token before executing transfers. NEVER auto-execute fund movements on mainnet.
- ALWAYS warn when targeting mainnet or exceeding safety thresholds (e.g., >100 USDC).
- ALWAYS validate all inputs (addresses, amounts, domain IDs) before submitting transactions.
- ALWAYS warn before interacting with unaudited or unknown contracts.
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The file defines both Solana mainnet and devnet contract sets, but the generic and legacy exports are permanently bound to devnet values. Any consumer that imports these supposedly generic constants may unintentionally interact with devnet addresses and RPC endpoints in production flows, causing misrouting of funds, failed mint/burn operations, or invalid attestations due to environment mismatch. In a crosschain payment and unified-balance skill, that configuration ambiguity is especially dangerous because callers may assume these exports are network-agnostic or production-safe.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The reference code signs an EIP-712 burn intent, submits signed transfer data to a remote Gateway API, and then performs on-chain Solana transactions, but the markdown provides no explicit warning that running or adapting this sample can move funds and interact with a third-party service. In a wallet-integrated crosschain transfer skill, omission of clear safety and consent messaging increases the risk that developers or end users trigger real asset movements or trust remote attestations without understanding the consequences.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The documentation and sample flow instruct a browser wallet signature, submission of signed data to a remote Gateway API, switching to another chain, and calling an on-chain mint function, but they do not explicitly warn users or integrators that these actions transmit signed payloads to a third party and can trigger irreversible blockchain side effects. In a cross-chain funds movement context, missing disclosure increases the risk of users approving actions they do not fully understand, which can lead to mistaken transfers, privacy leakage, or unintended asset movement.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This markdown file embeds code that POSTs the burn intent and wallet signature to an external Gateway API. While the flow mentions API submission, it does not clearly warn the user that signed transfer data and recipient details are transmitted off-wallet to a remote service.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This file provides a complete cross-chain USDC burn-and-mint workflow using developer-controlled wallets, but it does not include an explicit warning that executing the script will move real funds if pointed at funded wallets and mainnet settings. In the context of a payments and chain-abstraction skill, omission of such notice increases the risk of accidental value transfer, misuse in the wrong environment, or operators running examples without understanding the financial consequences.

Missing User Warnings

Low
Confidence
91% confidence
Finding
This markdown file outlines a transfer flow that includes submitting a signed burn intent to an external Gateway API, but it does not warn users that transfer details and signatures will be transmitted off-chain. For markdown files, SQP-2 applies when descriptions omit warnings about behaviors that may affect user privacy or data handling.

Missing User Warnings

Low
Confidence
89% confidence
Finding
The documentation instructs users to POST depositor addresses to Circle's external Gateway API, which creates a privacy and metadata exposure risk because wallet addresses and chain associations are transmitted to a third party. While this is expected for the feature to function and does not expose secrets by itself, the lack of any warning about external transmission, logging, or privacy implications can mislead integrators into sending user-linked addresses without informed consent or minimization.

Static analysis

No suspicious patterns detected.