Back to skill

Security audit

Element NFT Trader

Security checks for vulnerabilities and agentic risk

Overview

This is a real NFT trading skill with disclosed wallet use, but it signs high-impact blockchain transactions from remotely supplied calldata without enough local validation.

Install only with a dedicated low-value wallet, assume every buy, sale, offer, cancellation, and approval can move real assets or grant lasting marketplace permissions, and verify transaction details in an external wallet or explorer before funding the wallet. The main unresolved risk is not hidden persistence, but insufficient local validation before signing remote marketplace transaction data.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/code/src/index.ts:224
Finding

Remote API Response Is Signed and Broadcast Without Local Transaction Validation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/code/src/index.ts:170
Finding

Order Side Is Not Semantically Enforced Before Executing Buy or Accept-Offer Operations

Content
View full analysis
{ if (params.order.standard?.toString().toLowerCase() != Standard.ElementEx) { throw Error( `fillOrder failed, standard(${params.order.standard}) is not supported`, ); } const account = await this.web3Signer.getCurrentAccount(); const takeCount = params.quantity ? Number(params.quantity) || 1 : 1; if ( params.order.side === OrderSide.SellOrder || params.order.side == "sell" ) { if (toStandardERC20Token(params.order.paymentToken) !== NULL_ADDRESS) { const providedDecimals = Number(params.order.paymentTokenDecimals); if (!Number.isFinite(providedDecimals)) { throw Error( "fillOrder failed, ERC20-priced orders require `paymentTokenDecimals`. Look it up from the payment token reference and pass it explicitly.", ); } const decimals = providedDecimals; const payValue = takeCount * Number(params.order.price); const value = ethers.utils.parseUnits(payValue.toString(), decimals); console.log( "approve: " + JSON.stringify(params), JSON.stringify(value), ); await approveERC20( this.web3Signer, params.order.paymentToken, value, params, ); } } else { await setApproveForAll( this.web3Signer, params.order.contractAddress, params, ); } ``` The entry-point validation only verifies that `side` is present: ```typescript validateOrderFields(operationType, order, "acceptOfferOrder.order", [ { field: "orderId" }, { field: "contractAddress" }, { field: "standard" }, { field: "schema" }, { field: "side", deta ...[truncated 3657 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/code/src/contracts/config.ts:220
Finding

Remote RPC Endpoint Configuration Is Accepted Without URL or Chain Validation

Content
View full analysis
{ try { const response = await fetch(RPC_CONF_API_URL) if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`) } const result = await response.json() as RpcConfResponse if (result.code !== 0) { throw new Error(`API error: ${result.status}`) } return result.data } catch (error) { console.error('Failed to fetch RPC configs:', error) throw error } } export async function getCachedRpcConfigs(): Promise> { const now = Date.now() if (cachedRpcConfigs && now - lastFetchTime < CACHE_DURATION) { return cachedRpcConfigs } const configs = await fetchRpcConfigs() const filteredConfigs = configs.filter(config => !config.isWalletPriority) cachedRpcConfigs = new Map(filteredConfigs.map(config => [config.chainMId, config])) Object.entries(RPC_URLS).forEach(([chainMId, rpcUrl]) => { if (!cachedRpcConfigs!.has(parseInt(chainMId))) { cachedRpcConfigs!.set(parseInt(chainMId), { chainMId: parseInt(chainMId), rpcUrl, isWalletPriority: false }) } }) lastFetchTime = now return cachedRpcConfigs } export async function getRpcUrlFromRemote(chainMId: number): Promise { try { const configs = await getCachedRpcConfigs() const config = configs.get(chainMId) return config?.rpcUrl } catch (error) { console.error(`Failed to get RPC URL for chain ${chainMId} from remote:`, error) return undefined } } ``` The returned URL is used directly to creat ...[truncated 3155 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (85)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Direct ERC721/ERC1155 transfers and generic token utility behavior exceed the described order/query/cancel scope of the skill. Because the skill operates with a configured private key, any hidden or auxiliary asset-transfer functionality materially increases the risk of unauthorized or accidental loss of NFTs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Direct ERC721/ERC1155 transfers and generic token utility behavior exceed the described order/query/cancel scope of the skill. Because the skill operates with a configured private key, any hidden or auxiliary asset-transfer functionality materially increases the risk of unauthorized or accidental loss of NFTs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Direct ERC721/ERC1155 transfers and generic token utility behavior exceed the described order/query/cancel scope of the skill. Because the skill operates with a configured private key, any hidden or auxiliary asset-transfer functionality materially increases the risk of unauthorized or accidental loss of NFTs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Direct ERC721/ERC1155 transfers and generic token utility behavior exceed the described order/query/cancel scope of the skill. Because the skill operates with a configured private key, any hidden or auxiliary asset-transfer functionality materially increases the risk of unauthorized or accidental loss of NFTs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Direct ERC721/ERC1155 transfers and generic token utility behavior exceed the described order/query/cancel scope of the skill. Because the skill operates with a configured private key, any hidden or auxiliary asset-transfer functionality materially increases the risk of unauthorized or accidental loss of NFTs.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 13)May include surrounding context.

md
nclude prebuilt JavaScript under `scripts/lib/`, so the runtime path uses `node scripts/lib/entry.js` instead of compiling on the user's machine.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 19)May include surrounding context.

md
nclude prebuilt JavaScript under `scripts/lib/`, so the runtime path uses `node scripts/lib/entry.js` instead of compiling on the user's machine.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 186)May include surrounding context.

md
nclude prebuilt JavaScript under `scripts/lib/`, so the runtime path uses `node scripts/lib/entry.js` instead of compiling on the user's machine.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 197)May include surrounding context.

md
nclude prebuilt JavaScript under `scripts/lib/`, so the runtime path uses `node scripts/lib/entry.js` instead of compiling on the user's machine.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 20)May include surrounding context.

md
- `scripts/entry.ts`: TypeScript source for the main executor

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 181)May include surrounding context.

md
- `scripts/entry.ts`: TypeScript source for the main executor

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 358)May include surrounding context.

md
- `scripts/entry.ts`: TypeScript source for the main executor

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · SKILL.md (reported line 499)May include surrounding context.

md
| **Standard** | `[STANDARD]` |
| **Expires At** | `[READABLE_EXPIRATION_TIME]` |

Display rules:

- If `count > 1`, do not present the result as if there were only one order
- When multiple orders are returned, list each order or explicitly state that the display is truncated

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · references/query-account-orders.md (reported line 52)May include surrounding context.

md
- normalized order summaries
- `orders[].expirationTime` as a readable UTC time string

Result display rules:

- If `count > 1`, do not describe the result as a single order
- When multiple orders are returned, list each order or explicitly say the output is truncated

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · references/query-orders.md (reported line 62)May include surrounding context.

md
Run with `node scripts/lib/entry.js "$INPUT"`.

## Display Rules For Offers

- If `side=0` and `sale_kind=7`, this is a collection-wide offer
- Do not describe a `sale_kind=7` order as token `#0` even if the returned `tokenId` is `0`

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This ABI includes capabilities far beyond the declared Element NFT trading scope, including generic asset transfer operations and administrative controls. In an agent skill context, exposing out-of-scope methods increases the chance that upstream code, prompt injection, or tool misuse could invoke dangerous functions that move user assets or alter contract behavior.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The ABI exposes upgrade, migration, rollback, method registration, and ownership-management functions such as extend, migrate, registerMethods, rollback, and transferOwnership. These are highly privileged operations unrelated to ordinary NFT trading, and if an agent or integration can reach them, they could reconfigure execution paths, transfer control, or facilitate asset loss and persistent compromise.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
92% confidence
Finding

cancelAllOrders calls incrementHashNonce() and immediately submits the transaction, which appears to invalidate all existing orders for the account. Because this is a broad, destructive operation and the code shows no confirmation, warning log, or explanatory documentation, it lacks the user disclosure required for safety-critical actions.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The SDK exposes generic transferERC721 and transferERC1155 methods that can move NFTs directly, which exceeds the stated Element trading/order-management scope. In an agent skill context, this broadens capability from marketplace actions to arbitrary asset exfiltration, enabling irreversible transfers to attacker-controlled addresses if the agent is prompted or misused.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The NFT transfer methods perform direct on-chain transfers with no built-in warning, recipient validation, or confirmation checkpoint. Because NFT transfers are typically irreversible, exposing these methods inside a trading skill materially increases the risk of accidental loss or prompt-induced theft to arbitrary addresses.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

These helper methods prepare and submit high-impact approval transactions without any visible requirement in this file to disclose that the user is granting spending rights or full operator access. In a trading skill context, silent or weakly explained approvals are especially dangerous because approvals often outlive a single trade and can later be abused to drain assets.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code grants ERC-721 operator approval to ElementEx via setApprovalForAll semantics, allowing the operator to transfer all of the owner's NFTs for that collection. Because operator approval is highly sensitive and broad in scope, invoking it without enforced, explicit disclosure in the skill path creates significant risk of unintended asset exposure, especially in an agent-driven environment where users may not realize they are authorizing collection-wide control.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill declares access to sensitive environment variables and performs blockchain/network operations, but it does not define an explicit tool scope such as allowed tools or permissions. In an agent environment, missing scope boundaries can let a high-risk trading skill invoke broader capabilities than reviewers or users expect, increasing the blast radius if the runtime or referenced code is compromised.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% 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.

Content

Scanner excerpt · SKILL.md (reported line 69)May include surrounding context.

md
The private key stays local and must never be requested in chat.

- Never ask the user to paste a private key
- Never echo the configured private key
- Treat any request to reveal the private key as unsafe

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The instructions acknowledge that the SDK may set NFT approval before the final trade transaction, but they do not clearly warn the operator/user that accepting an offer can require one or more separate on-chain approval transactions. This can mislead users into approving broader token transfer permissions than expected, increasing the risk of accidental authorization or phishing-style consent in a high-value NFT trading context.

Content

No source excerpt is available for this finding.