Back to skill

Security audit

Abstract Toolkit

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real blockchain automation helper, but it can move mainnet funds with raw private keys and has weak safeguards around irreversible transactions.

Review this carefully before installing. Use only a dedicated low-value wallet, test on testnet or tiny amounts first, pin dependencies, and manually verify every destination, router, bridge route, contract function, and transaction before signing. Do not use a primary or treasury private key with this skill as written.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/relay-bridge.js:90
Finding
Bridge Script Sends Mainnet ETH Without Destination Routing Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/relay-bridge.js:90-99` **Vulnerability Type**: Unsafe bridge transaction construction **Risk Level**: High ### Vulnerable Code ```javascript // Relay uses a simple deposit to their contract // The Relay API handles the rest console.log(`\nSending to Relay depositor: ${chain.relayDepositor}`); const tx = await wallet.sendTransaction({ to: chain.relayDepositor, value: amountWei, data: "0x" // Simple ETH transfer }); ``` ### Technical Analysis The script claims to bridge ETH to Abstract, but it does not request a bridge quote or transaction from Relay, submit destination-chain parameters, encode the destination chain ID, or explicitly provide the destination recipient. Instead, it sends a plain ETH transfer with empty calldata to a hard-coded address. The comment states that the Relay API handles the remainder, but the implementation does not call a Relay API. A confirmed source-chain transaction therefore establishes only that ETH was transferred to the configured address; it does not prove that a valid route to Abstract was created. The script then reports the source transaction as a successful deposit and states that Relay will bridge it, without verifying destination-chain settlement. ### Attack Path 1. A user follows the bridge instructions in `SKILL.md` and exports a funded private key. 2. The user runs `relay-bridge.js` with a source chain and amount. 3. The script constructs a plain ETH transfer to the configured hard-coded address. 4. No route, quote, destination recipient, destination chain, or bridge-specific calldata is obtained or validated. 5. The source transaction confirms, and the script reports success. 6. The transferred ETH may not arrive on Abstract and may be difficult or impossible to recover. ### Impact Assessment The affected privilege is the signing authority of the wallet supplied through `WALLET_PRIVATE_KEY`. The scope is the amount submitted by each invoca ...[truncated 363 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Obtain the bridge transaction from Relay's documented quote or transaction API rather than constructing a plain ETH transfer. 2. Explicitly supply and validate: - Source chain ID. - Destination chain ID `2741`. - Source and destination tokens. - Destination recipient. - Input amount and expected output amount. 3. Validate the API response before signing: - Confirm the transaction target is an approved Relay contract. - Confirm the returned chain ID matches the selected source chain. - Confirm the transaction value equals the approved amount. - Reject empty or unexpected calldata unless the official protocol specification explicitly requires it. 4. Display the complete route, fees, recipient, minimum output, and target contract and require explicit user confirmation. 5. Verify the provider-reported chain ID before sending. 6. Report source submission and destination settlement as separate states. Do not report a completed bridge until the destination transaction or balance change has been verified. 7. Add testnet integration tests and small-value route tests before enabling mainnet by default. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/transfer.js:61
Finding
Successful Transfers Are Reported as Failures Due to Block-Scoped Transaction Variables<![CDATA[ ## Vulnerability Details **File Location**: `scripts/transfer.js:61-92` **Vulnerability Type**: Incorrect transaction-state reporting **Risk Level**: Medium ### Vulnerable Code ```javascript if (!token) { // Transfer ETH const tx = await wallet.sendTransaction({ to: to, value: ethers.parseEther(amount) }); console.log(`TX: ${tx.hash}`); const receipt = await tx.wait(); console.log(`✅ Transfer complete! Block: ${receipt.blockNumber}`); } else { // Transfer token const tokenAddress = TOKENS[token] || token; const contract = new ethers.Contract(tokenAddress, ERC20_ABI, wallet); const decimals = await contract.decimals(); const symbol = await contract.symbol(); const amountParsed = ethers.parseUnits(amount, decimals); // Check balance const balance = await contract.balanceOf(wallet.address); if (balance < amountParsed) { console.error(`Insufficient balance. Have: ${ethers.formatUnits(balance, decimals)} ${symbol}`); process.exit(1); } const tx = await contract.transfer(to, amountParsed); console.log(`TX: ${tx.hash}`); const receipt = await tx.wait(); console.log(`✅ Transfer complete! Block: ${receipt.blockNumber}`); } console.log(`Explorer: https://abscan.org/tx/${tx?.hash || ""}`); ``` ### Technical Analysis Each `tx` variable is declared with `const` inside its respective conditional block. JavaScript block scoping makes neither variable accessible after the closing brace. After a transfer has already been submitted and confirmed, the final explorer log attempts to evaluate `tx`. This raises a `ReferenceError`. The surrounding `try/catch` catches that exception and prints `Transfer failed`, even though the blockchain transaction has completed successfully. This produces an unsafe mismatch between on-chain state and the process result. Automated Agents, scripts, or users commonly retry operations reported as failed, but blockchain transfers are not idempotent. ### Attack Path 1 ...[truncated 958 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Declare the transaction variable before the conditional and assign it in each branch: ```javascript let tx; if (!token) { tx = await wallet.sendTransaction({ to, value: ethers.parseEther(amount) }); } else { tx = await contract.transfer(to, amountParsed); } console.log(`TX: ${tx.hash}`); const receipt = await tx.wait(); if (receipt.status !== 1) { throw new Error(`Transaction reverted: ${tx.hash}`); } console.log(`Explorer: https://abscan.org/tx/${tx.hash}`); ``` 2. Emit the transaction hash immediately after submission so it remains available even if receipt polling or later reporting fails. 3. Distinguish submission failures, confirmation timeouts, reverted transactions, and post-confirmation display errors. 4. Return structured output containing the transaction hash, receipt status, block number, chain ID, recipient, and amount. 5. Before retrying, query the original transaction hash or use an application-level idempotency record. 6. Add tests for both transfer branches that assert a confirmed transfer exits successfully and never reports failure because of subsequent logging. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:103
Finding
Security-Sensitive Dependencies and Compiler Are Installed Without Version Pinning<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:103-111`; `references/hardhat.config.js:15-18`; `references/troubleshooting.md:23-25` **Vulnerability Type**: Unpinned executable dependencies and compiler toolchain **Risk Level**: Medium ### Vulnerable Code `SKILL.md:103-111`: ```bash # Core dependencies npm install ethers zksync-ethers viem # For contract deployment npm install @matterlabs/hardhat-zksync # For AGW (Abstract Global Wallet) npm install @abstract-foundation/agw-client ``` `references/hardhat.config.js:15-18`: ```javascript zksolc: { // Uses zksolc from npm - no manual download needed version: "latest", settings: {} }, ``` `references/troubleshooting.md:23-25`: ```bash # Install zksolc npm install -g @matterlabs/zksolc ``` ### Technical Analysis The project instructs users to install wallet, blockchain, deployment, and compiler packages without exact versions. It also configures `zksolc` as `"latest"` and recommends a global unpinned compiler installation. These components execute with access to security-sensitive data and operations. Wallet libraries can process `WALLET_PRIVATE_KEY` and construct signed transactions, while compiler and deployment plugins can alter generated bytecode or deployment behavior. Resolving versions dynamically means the effective code may differ from the code used during this audit. No package manifest or lockfile was present in the reviewed directory structure to provide deterministic dependency resolution or integrity control. ### Attack Path 1. A user follows the documented dependency-installation commands. 2. npm resolves the current package versions rather than versions reviewed with this Skill. 3. A compromised, malicious, or unexpectedly incompatible future release is installed. 4. The package executes when a wallet, compiler, deployment script, or Hardhat configuration is used. 5. Depending on the affected package, it may read environment variables, modify transaction constru ...[truncated 851 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add a `package.json` containing exact, audited dependency versions rather than version ranges. 2. Commit a lockfile and require deterministic installation through `npm ci`. 3. Pin `zksolc` to a specific reviewed version instead of `"latest"`. 4. Remove the recommendation to install the compiler globally. Use a project-local development dependency with a locked version. 5. Enable lockfile integrity verification and review package provenance, maintainers, release history, and transitive dependencies. 6. Run dependency vulnerability and malware scanning in CI. 7. Treat updates to wallet libraries, signing libraries, Hardhat plugins, and compilers as security-sensitive changes requiring code review and regression testing. 8. Use a dedicated low-value test key and testnet during dependency validation. Do not expose production private keys to newly resolved dependencies before review. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The documented behavior and the described capability surface do not line up cleanly: the skill introduces AGW creation and references broad operational abilities without a tightly bounded, auditable implementation contract. In security-sensitive blockchain workflows, this mismatch can mislead users or orchestrators about what actions the skill may perform, increasing the risk of unintended wallet setup or asset-affecting operations.

Ae1

High
Category
analysis-evasion
Content
node scripts/check-balances.js <wallet> all
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/check-balances.js <wallet> all
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill clearly relies on sensitive environment-provided credentials such as WALLET_PRIVATE_KEY, but the manifest declares no explicit tool scope or permissions boundary. In an agent setting, missing scope declarations can cause overbroad access to secrets or make operators unaware that the skill is capable of initiating authenticated on-chain actions.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The documentation repeatedly instructs users to export WALLET_PRIVATE_KEY without any warning about credential sensitivity, secure storage, shell history leakage, or reuse risk. Exposing raw private keys in a general-purpose agent workflow materially increases the chance of secret theft and total wallet compromise.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill provides ready-to-run instructions for bridging, deploying contracts, transferring tokens, swapping assets, and writing to arbitrary contracts, yet it does not prominently warn that these are irreversible on-chain operations that may result in permanent fund loss. In an agent-driven context, this omission is especially dangerous because users may treat the workflow as routine automation rather than high-risk financial execution.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation instructs users to export a raw wallet private key into an environment variable and immediately use it for blockchain operations, but provides no warning about secure handling, shell history exposure, process inspection, or safer alternatives. In a skill focused on deploying contracts and moving assets, this can directly lead to theft of funds if users copy real funded keys into insecure environments or shared agent/runtime contexts.

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
95% confidence
Finding
In write mode, the script immediately submits whatever contract function, arguments, and ETH value were provided on the command line, with no confirmation, allowlist, simulation, or human review step. In an agent skill intended to deploy contracts, bridge assets, trade, and transfer funds on mainnet, this makes accidental or prompt-influenced irreversible transactions materially more dangerous.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The script directly submits approval and swap transactions once invoked, without any final confirmation step that shows the exact token, amount, router, path, and minimum output. In an agent skill context, this increases the chance of unintended irreversible asset movement due to bad parameters, prompt injection into tool usage, or operator error, especially because approvals and swaps can immediately change token balances and expose allowance to the configured router.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The script reads WALLET_PRIVATE_KEY from the environment to authorize blockchain transfers, which is a sensitive credential operation. Although the usage comment tells the user to set the variable, it does not warn about the security implications of exposing or mishandling a private key.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script performs irreversible ETH and token transfers immediately after parsing CLI arguments, without any confirmation prompt, simulation, or recipient sanity checks. In an agent skill that is explicitly designed to move assets on mainnet, this increases the chance that a mistaken address, wrong token symbol/address, or malformed amount will result in permanent loss of funds.

Static analysis

No suspicious patterns detected.