Back to skill

Security audit

Okx Growth Competition

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed OKX competition helper, but reward claiming can sign backend-provided blockchain transactions without documented validation and it may inspect other wallet accounts.

Install only if you are comfortable giving this skill competition API access plus wallet-mediated join and claim authority. Before claiming rewards, verify the wallet, chain, recipient, amount, and transaction details through a trusted wallet or OKX interface, and avoid letting it inspect unrelated wallet accounts unless you intend that.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (2)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:355
Finding

Unnecessary Enumeration and Disclosure of Additional Wallet Accounts

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 355-369
Vulnerability Type: Excessive wallet-account access and cross-account correlation
Risk Level: Medium

Vulnerable Code Snippet

text
- `[accountName]` ← `accountName` of the currently selected account (read from `wallet_store` / `wallet status`, e.g. `Account 1`)
text
- `[registeredAccountName]` ← name of the OTHER account in the same login that holds the registration. To find it, iterate every account from `wallet_store` other than the current one and call `competition_user_status` for the activity, picking the one whose `joinStatus=1`. If no account is found (rare race), fall back to a generic phrase like `another of your wallet accounts is already registered` and ask the user to check `onchainos wallet status` themselves.

Technical Analysis

When a competition registration fails because another account under the same login is already registered, the Skill instructs the Agent to inspect every account in wallet_store and submit status queries for each account.

This exceeds the minimum access required to handle the registration failure. The Skill already documents a privacy-preserving fallback that reports that another account is registered without identifying or querying it. Enumerating all accounts is therefore not necessary for the declared operation.

Wallet addresses are public identifiers, but their association with one authenticated user is sensitive financial metadata. Querying each account through competition_user_status can disclose that association to the competition service and expands access beyond the currently selected account.

Attack Path

  1. A user attempts to register the currently selected wallet for a competition.
  2. The backend returns duplicate-registration error code=11016.
  3. Following the Skill instructions, the Agent reads all accounts from wallet_store.
  4. The Agent calls `competition_ ...[truncated 930 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not enumerate accounts other than the currently selected account automatically.
  2. On duplicate registration, use the documented generic response: another wallet account is already registered.
  3. Require the user to explicitly select an account before querying its competition status.
  4. Limit competition_user_status calls to the selected wallet and requested competition.
  5. Avoid sending account names, internal account identifiers, or unrelated addresses unless strictly required by the backend.
  6. Document what wallet metadata is transmitted and obtain clear consent before performing cross-account lookups.
  7. Add an authorization boundary to wallet tooling so a Skill cannot iterate all accounts without a distinct, user-approved permission.

T09 · Insecure Skill Coding Practices

Error
Location
references/cli-reference.md:256
Finding

Backend-Supplied Claim Transactions Are Signed Without Documented Semantic Validation

Content
View full analysis

Vulnerability Details

File Location: references/cli-reference.md, lines 256-260; related instructions in SKILL.md, lines 579-635
Vulnerability Type: Blind signing and broadcasting of remotely assembled transaction calldata
Risk Level: High

Vulnerable Code Snippet

text
Internally the command:
1. Calls `competition_user_status` to verify `rewardStatus == 1` (won, unclaimed). Bails with a plain error if 0/2/3.
2. Calls the claim API to fetch unsigned calldata for each entry.
3. For Solana entries: extracts the unsigned tx bytes from `tx.data` (Buffer JSON shape) and base58-encodes them locally — empirically `base58CallData` is empty in real responses, so this fallback is always taken.
4. For EVM entries: takes the 0x-prefixed `input` directly.
5. Pipes each entry through `wallet contract-call` (TEE session signing + broadcast) and collects the resulting txHash.

The corresponding Skill instructions state:

text
Both the MCP tool `competition_claim` and the CLI `onchainos competition claim` now do the **same atomic flow**: pre-check `rewardStatus`, fetch calldata, sign each entry with the TEE session, broadcast on-chain, return txHash array.
text
- ❌ Do NOT inspect the result for an empty `base58CallData` and conclude the CLI cannot sign a Solana claim — that field is empirically empty for Solana; the CLI/MCP code internally falls back to encoding `tx.data` byte array via base58 and proceeds. Just trust the `succeeded[]` and `failed[]` arrays.

Technical Analysis

The claim workflow obtains unsigned transaction data from a remote backend and passes it to a TEE-managed wallet for signing and broadcast. The documented workflow validates only that the user has an unclaimed reward. It does not document local validation of:

  • The destination contract or Solana program.
  • The chain identifier.
  • The EVM method selector or Solana instruction set.
  • Native currency value tr ...[truncated 2269 chars]
Remediation
View remediation

Remediation Suggestions

  1. Decode and semantically validate every backend-supplied transaction before signing.
  2. Maintain strict allowlists of permitted claim contracts, Solana programs, chains, methods, and instruction types.
  3. Verify that the destination, recipient, activity identifier, reward asset, and reward amount match independently retrieved competition data.
  4. Reject unexpected native value, token approvals, delegate changes, arbitrary transfers, proxy upgrades, or additional instructions.
  5. For EVM transactions, validate the chain ID, target address, method selector, decoded arguments, and value.
  6. For Solana transactions, validate the recent blockhash handling, account list, signer and writable privileges, program IDs, instruction data, and absence of unrelated instructions.
  7. Present a human-readable transaction summary and require explicit confirmation immediately before signing.
  8. Cryptographically authenticate transaction-assembly responses and bind them to the requested user, wallet, activity, chain, amount, and expiration time.
  9. Simulate the validated transaction and compare resulting balance and approval changes against a strict expected-state policy.
  10. Fail closed when calldata fields are missing or malformed rather than automatically reconstructing and signing an opaque fallback payload.
  11. Log validation decisions and transaction hashes without recording private keys, session secrets, or other signing material.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (8)

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 41)May include surrounding context.

md
Quick router (user intent → template section):

- "list competitions / show available competitions" → **Step 1** (table, optionally split by Active / Ended)
- "show details / show rules / show prize pool" → **Step 2** (Basic info block + 4 reward sections, with hardcoded `Solana, {chainName}` and required participation / Skill copy)
- "register / join" → **Step 3** (registration success fixed template + disclaimer)
- "trade for me" → **Step 4** (delegate to okx-dex-swap)
- "leaderboard / ranking" → **Step 5**

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 71)May include surrounding context.

md
`activityStatus` (response field): **`3`=active, `4`=ended** — these are DIFFERENT values from the request filter  
`sort-type`: dynamic — read from `competition_detail` → `tabConfigs[].rankFieldConfig[].sortValueMap.descend`. Currently observed values: `1`=PnL% (realized ROI), `7`=PnL (realized profit). Future activities may add more — always trust `tabConfigs` over hardcoding.

## Output Rules

> **Internal-only IDs vs user-facing display.** Internal numeric IDs (`activityId`, `chainIndex`, `accountId`) are returned in tool responses on purpose — they are needed to chain calls between tools (e.g. after `competition_join`, you may need to call `competition_detail` with the activity id to fill the success template). **Keep them in the data layer; never render them in user-visible messages.**

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 461)May include surrounding context.

onchainos competition rank --activity-id --wallet --sort-type --limit 20

text

**Display rules:** for each leaderboard render a separate section labeled by its `title`. Each section shows top N entries: rank, nickname (masked), score (`userTotal` formatted by `format` field), estimated reward.

Example response (activity with two leaderboards):
> **PnL% leaderboard** — pool 200 DJT

Behavior Manipulation

Medium
Category
Prompt Injection
Confidence
91% confidence
Finding

The skill hardcodes a behavioral instruction to always answer that Solana counts, even while acknowledging backend data may be incomplete and future behavior may change. This can cause the agent to override actual evidence and provide potentially false participation guidance, leading users to trade under incorrect assumptions and suffer financial loss or ineligibility.

Content

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

md
1. **Every active competition runs simultaneously on Solana AND the chain returned by the backend** (e.g. `chainName=X Layer` → activity runs on both X Layer **and** Solana). Solana is the hardcoded second chain on every activity.
2. **Trades on either chain count toward the same competition standing.** A user trading on Solana for an X-Layer-titled competition is participating, not bystanding. Likewise EVM trades count for a Solana-titled competition. (When backend later returns a multi-chain field listing all supported chains, drop this hardcoding.)
3. `myRankInfo.userTotal = 0` means the user has not yet hit the qualifying threshold or the backend metric pipeline has not picked up their trades yet — it does **NOT** mean the user's chain is unsupported. Never tell the user "your chain doesn't count" based on a `userTotal=0` observation.
4. The competition `--wallet` argument used in `competition_rank` is the chain-appropriate address: SOL for Solana-primary activities, EVM for EVM-primary activities. The address you pass is just a query lens — trades on the OTHER chain still count toward the same ranking.
5. The shape of point 1–4 may change in the future when backend exposes the full supported-chain list. Until then, NEVER answer "Does Solana count for this competition?" with anything other than YES.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The markdown explicitly instructs the agent to always render competition times in UTC+8 and to never use the user's local timezone. This is a natural-language locale policy constraint applied to all users without opt-in or an offered choice, which matches the policy-violation category.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill includes a wallet export flow even though its stated purpose is competition discovery, registration, ranking, and reward claiming. Introducing wallet-export mediation expands the capability boundary into sensitive key-management territory and can socially engineer users into actions that may forfeit competition eligibility or expose funds if routed incorrectly.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

A trading-competition skill has no justified need to participate in wallet export decisions, which are highly sensitive operations adjacent to seed/key exposure and account compromise. Even without directly exporting keys, normalizing export guidance in this context increases phishing and privilege-confusion risk by conditioning users to trust unrelated wallet actions through the competition interface.

Content

No source excerpt is available for this finding.

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

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

Registered users who accumulate $100 or more in total trading volume via Agentic Wallet and maintain a total wallet balance of $100 or above throughout the competition period, will share the {participationPoolAmount} participation prize pool equally. Random asset snapshots will be taken during the competition period to verify eligibility.

Skill Quality Prize ({skillPoolAmount}) The Skill Quality Prize is an independently judged award. During the competition period, participants may submit their Agent Skills through the event landing page. Eligible submissions include, but are not limited to, on-chain autonomous yield strategies, trading analysis, and trading signal monitoring. All submitted Agent Skills will be evaluated through a dual-review process combining AI pre-screening and manual judging. The top {skillTopN} Skill creators by score will each receive a reward of {skillPerCreatorReward}.

text

#### Field-mapping rules