Back to skill

Security audit

Near Airdrop Hunter

Security checks for vulnerabilities and agentic risk

Overview

The skill does not appear to steal funds or credentials, but it overstates crypto airdrop claiming and records manual, unverified actions as claimed.

Review this skill carefully before installing. It appears to be a lightweight URL-and-tracking helper, not a real airdrop checker or claimer. Do not rely on its claimed history as proof that rewards were claimed, and independently verify any claim links and wallet prompts before signing anything.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/airdrop.js:100
Finding
Unverified Airdrop Claims Are Persisted as Successfully Claimed## Vulnerability Details **File Location**: `scripts/airdrop.js:100-122` **Vulnerability Type**: Unverified financial workflow state transition **Risk Level**: Medium The claim workflow records an airdrop in the `claimed` collection even though no wallet connection, transaction signature, protocol request, or on-chain confirmation occurs. ```js async function claimAirdrop(accountId, airdropId) { const airdrop = KNOWN_AIRDROPS[airdropId]; if (!airdrop) { throw new Error(`Unknown airdrop: ${airdropId}`); } console.log(`Claiming airdrop for ${accountId} on ${airdrop.name}...`); console.log(` Claim URL: ${airdrop.claimUrl}`); console.log(` Note: Visit the URL to claim manually`); console.log(` Integration requires wallet connection and signing`); const tracking = await loadTracking(); tracking.claimed.push({ airdrop: airdropId, account: accountId, timestamp: new Date().toISOString() }); await saveTracking(tracking); return { airdrop: airdrop.name, account: accountId, status: 'claim_required', message: 'Visit the claim URL to complete claiming' }; } ``` The misleading success message is subsequently emitted at `scripts/airdrop.js:164-165`: ```js await claimAirdrop(arg1, arg2); console.log('✅ Claim tracked! Complete via the claim URL.'); ``` ### Technical Analysis The implementation violates workflow-state integrity by transitioning directly to `claimed` before the required external action is completed. The returned `claim_required` status confirms that the operation remains pending, but the persisted state and reporting commands treat it as completed. Neither proof of wallet ownership nor a transaction receipt is required. Any caller can therefore create arbitrary claimed records for any syntactically supplied account ID. Repeated invocations also append duplicate entries because no uniqueness or idempotency check is perform ...[truncated 1236 chars]
Remediation
## Remediation Suggestions 1. Store an initial claim request with a `pending` or `action_required` status rather than adding it to `claimed`. 2. Move the record to `claimed` only after verifying a successful transaction through a trusted protocol endpoint or NEAR RPC query. 3. Persist verifiable evidence such as the transaction hash, block height, recipient account, airdrop identifier, and confirmation timestamp. 4. Validate that the confirmed transaction corresponds to the expected account and airdrop contract. 5. Add idempotency controls using a unique key such as `accountId + airdropId`, preventing duplicate records. 6. Separate pending, failed, and confirmed operations in the tracking schema. 7. Change the CLI message to explicitly state that no claim has occurred until confirmation is available. 8. Validate the tracking-file schema before mutation and use atomic file replacement to reduce corruption risks.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill promises automated discovery, eligibility checking, claiming, and tracking, but the described behavior is materially broader than what is actually implemented. In a financial/crypto context, this can mislead users into believing claims were verified or executed when they were not, causing missed rewards, incorrect operational decisions, or unsafe manual interaction with third-party claim links.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The README instructs users to run a claim command for an airdrop without warning that claiming may trigger wallet interactions, signature requests, on-chain transactions, fees, or changes to account state. In a crypto-related skill, omission of these effects can mislead users into executing sensitive operations without understanding the security and financial consequences.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill describes automatic airdrop claiming and storing tracking data in a local file, but it does not clearly warn users about account-impacting actions or persistent local data storage. In a crypto wallet context, even implied claiming behavior is sensitive because users may assume wallet-affecting operations are safe or expected, and may not realize account identifiers and claim history are being retained locally.

External Transmission

Medium
Category
Data Exfiltration
Content
const KNOWN_AIRDROPS = {
  aurora: {
    name: 'Aurora',
    checkUrl: 'https://api.aurora.dev/airdrop/eligibility',
    claimUrl: 'https://aurora.dev/claim'
  },
  ref: {
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
},
  ref: {
    name: 'Ref Finance',
    checkUrl: 'https://api.ref.finance/airdrop/eligibility',
    claimUrl: 'https://ref.finance/claim'
  },
  metapool: {
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
},
  metapool: {
    name: 'Meta Pool',
    checkUrl: 'https://api.metapool.app/airdrop/eligibility',
    claimUrl: 'https://metapool.app/claim'
  }
};
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The skill advertises eligibility checking and claiming rewards, but the implementation only prints URLs and records local state as if a claim were tracked. This can mislead users or higher-level agents into believing an eligibility check or claim workflow occurred when it did not, creating integrity and trust issues around financial actions.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The claimAirdrop function does not claim anything but still appends a claimed record and reports success-like progress to the user. In an airdrop/crypto context, falsely recording a completed or pending financial action can cause users or orchestration systems to skip real claiming steps or rely on inaccurate records.

Static analysis

No suspicious patterns detected.