Back to skill

Security audit

Agent Outlier

Security checks for vulnerabilities and agentic risk

Overview

This skill is for an on-chain paid game and is mostly disclosed, but it gives broad wallet-signing authority to unpinned code and includes an unbounded paid play loop.

Install only if you understand this can spend real ETH on Base mainnet. Use a dedicated low-balance wallet, pin and audit dependency versions, avoid the continuous play loop, and require explicit confirmation and spending limits before any commit, reveal, finalize, claim, or playRound action.

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

T08 · Insecure Dependencies

Error
Location
SKILL.md:42
Finding
Unpinned Third-Party SDK Receives Access to a Mainnet Wallet Signer<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 42-53 **Vulnerability Type**: Unpinned security-sensitive dependency **Risk Level**: High ### Vulnerable Code ```bash npm install agent-outlier-sdk ethers ``` ```js const { OutlierPlayer } = require('agent-outlier-sdk'); const { ethers } = require('ethers'); const provider = new ethers.JsonRpcProvider('https://mainnet.base.org'); const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider); const player = new OutlierPlayer(wallet, { exoTokenId: YOUR_EXO_TOKEN_ID }); ``` ### Technical Analysis The installation command does not pin exact package versions, enforce package integrity, or provide a reviewed lockfile. Consequently, the effective implementation installed by a user can change after the Skill has been reviewed. This is particularly security-sensitive because `agent-outlier-sdk` is subsequently loaded into the same Node.js process as `PRIVATE_KEY` and receives an `ethers.Wallet` signer connected to Base mainnet. Code executing in that process can inspect process environment variables and invoke wallet-signing operations. The SDK implementation is not included in the audited project, so the Skill's assertion that the private key is never stored or transmitted cannot be verified from the available source. NPM lifecycle scripts may also execute during installation with the permissions of the user running `npm install`. This expands the potential impact beyond blockchain transactions to resources accessible by that local user. ### Attack Path 1. An attacker compromises the published `agent-outlier-sdk` package, its maintainer account, or a transitive dependency, or causes an unsafe future version to be installed. 2. A user follows the unpinned `npm install agent-outlier-sdk ethers` instruction. 3. Malicious code executes through an installation lifecycle script or when the package is imported. 4. At runtime, the package operates in a process containing `process.env.PRIVATE ...[truncated 824 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `agent-outlier-sdk`, `ethers`, and all transitive dependencies to exact reviewed versions. 2. Include a lockfile and require reproducible installation with `npm ci` rather than unconstrained `npm install`. 3. Verify package provenance, signatures where available, registry ownership, and published integrity hashes. 4. Audit or vendor the complete SDK source before granting it access to a wallet signer. 5. Disable npm lifecycle scripts with `--ignore-scripts` unless specific reviewed scripts are required. 6. Run the SDK in a restricted environment with minimal filesystem, environment-variable, and network access. 7. Use a dedicated wallet containing only the funds required for a limited number of rounds; never use a primary wallet. 8. Add transaction-policy enforcement outside the SDK, including allowed chain, contract address, function selector, value, gas, and cumulative-spend limits. 9. Require users to verify the Base chain ID and destination contract before signing. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:174
Finding
Unbounded Autonomous Loop Can Repeatedly Spend Mainnet Funds<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 174-192 **Vulnerability Type**: Unbounded paid transaction loop **Risk Level**: High ### Vulnerable Code ```js async function playForever(player) { while (true) { try { // Pick strategy: weighted toward high end of range const picks = [ Math.floor(Math.random() * 15) + 36, // 36-50 Math.floor(Math.random() * 15) + 36, Math.floor(Math.random() * 15) + 36, ]; const result = await player.playRound(TIER.NANO, picks); console.log(`Round ${result.roundId}: ${result.won ? 'WON' : 'lost'}`); } catch (e) { console.error('Round error:', e.message); await new Promise(r => setTimeout(r, 30000)); // wait 30s on error } } } playForever(player); ``` ### Technical Analysis The example continuously invokes `player.playRound` inside an unconditional `while (true)` loop. Each successful round can perform multiple Base mainnet transactions and incur both a non-refundable entry fee and gas costs. There is no maximum round count, cumulative-spend limit, gas-price ceiling, wallet-balance reserve, execution deadline, cancellation signal, or per-round user confirmation. Exceptions only introduce a 30-second delay before retrying, so persistent errors or unexpected SDK behavior do not safely terminate execution. Because the Skill explicitly states that entry fees are non-refundable after commitment, this pattern creates direct and potentially continuing financial exposure. ### Attack Path 1. A user configures a funded Base mainnet wallet and starts the documented `playForever` example. 2. The loop invokes `player.playRound(TIER.NANO, picks)` without requesting further approval. 3. Each iteration signs and submits paid commit, reveal, finalize, and potentially claim transactions. 4. After a completed round, the loop immediately begins another round. 5. If an error occurs, execution waits for 30 seconds and retries rather than st ...[truncated 901 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the unconditional infinite-loop example or make continuous play an explicitly enabled advanced feature. 2. Require a finite `maxRounds` value and stop when that limit is reached. 3. Enforce a cumulative entry-fee and gas budget outside the third-party SDK. 4. Maintain a minimum wallet-balance reserve that must never be spent. 5. Add maximum transaction-value and gas-price limits for every operation. 6. Require explicit confirmation before each paid round, particularly when running on mainnet. 7. Add an `AbortSignal`, execution deadline, and safe shutdown handling. 8. Stop after repeated failures instead of retrying indefinitely; use a bounded retry count with exponential backoff. 9. Simulate and validate every transaction before signing, including chain ID, destination contract, function selector, ETH value, and expected phase. 10. Use a dedicated low-balance wallet so residual defects cannot expose unrelated funds. 11. Record cumulative fees and gas costs and display them before requesting authorization for another round. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Vague Triggers

Medium
Confidence
95% confidence
Finding
The skill description uses broad trigger phrases such as 'outlier', 'arena', 'commit', 'reveal', and 'finalize', which can match ordinary crypto, gaming, or governance conversations that are not requests to use this specific skill. Because this skill can sign paid on-chain transactions using a configured private key, accidental invocation increases the chance of unintended wallet actions and financial loss.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The continuous-play example implements an infinite loop that repeatedly calls a paid transaction flow (`playRound`) without a prominent warning, budget cap, stop condition, or human confirmation. In this skill's context, each iteration can spend ETH entry fees and gas on Base mainnet, so users may unknowingly authorize unbounded financial loss if the pattern is copied or automated by an agent.

Static analysis

No suspicious patterns detected.