Back to skill

Security audit

Polymarket Cryptos Maker 5m

Security checks for vulnerabilities and agentic risk

Overview

This is a real-money autonomous Polymarket trading skill with a coherent purpose, but its background execution and unreliable safeguards need manual review before installation.

Review this carefully before installing or running it with a funded wallet. Treat live mode as capable of placing real orders continuously until manually stopped, and do not rely on the advertised 8% stop-loss as an account-level protection. Safer use would require foreground or bounded execution, clear stop and monitoring commands, strict share and notional caps, authenticated fill and balance reconciliation, and pinned dependencies.

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
index.mjs:140
Finding

Live order fills are not tracked, rendering the stop-loss ineffective

Content
View full analysis
= MAKER_SPREAD) upFilled = true if (!dnFilled && curDn.bid >= MAKER_SPREAD) dnFilled = true } if (timedOut && !expired) { if (!upFilled && LIVE_TRADING) await clob.cancelOrder(upOrderId).catch(() => {}) if (!dnFilled && LIVE_TRADING) await clob.cancelOrder(dnOrderId).catch(() => {}) if (!upFilled && !dnFilled) { return { status: "SKIPPED", asset: assetKey, pnl: 0 } } } ``` The resulting PnL is only applied when a cycle reports success: ```js let cyclePnL = 0 for (const result of results) { if (result.status === "SUCCESS") { cyclePnL += result.pnl totalTrades++ } } currentBalance += cyclePnL ``` ### Technical Analysis Order-fill simulation is performed only when `LIVE_TRADING` is false. In live mode, neither `upFilled` nor `dnFilled` is updated through an authenticated order-status, trade, or fill query. After the timeout, the code attempts to cancel both orders and suppresses cancellation errors. It then returns `SKIPPED` with zero PnL because both fill flags remain false. This can happen even if one or both orders were fully or partially executed before cancellation. As a result, live executions, partial fills, cancellation races, and cancellation failures are not reflected in the local PnL calculation. The drawdown calculation therefore cannot reliably trigger the advertised 8% stop-loss. ### Attack Path 1. A user enables `LIVE_TRADING=true` and supplies a funded wallet private key. 2. The process submits sell orders to Polymarket. 3. One or both orders are fully or partially filled within the cancellation window. 4. The impl ...[truncated 1165 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
index.mjs:19
Finding

The advertised global stop-loss is based on a fabricated local balance

Content
View full analysis
dailyPeak) { dailyPeak = currentBalance } // 2. Calcul du Drawdown const drawdown = (dailyPeak - currentBalance) / dailyPeak // 3. Déclenchement du STOP LOSS if (drawdown >= STOP_LOSS_PCT) { console.log( JSON.stringify({ status: "HALTED", reason: "STOP_LOSS_REACHED", drawdown: `${(drawdown * 100).toFixed(2)}%`, final_balance: parseFloat(currentBalance.toFixed(2)), total_cycles: totalTrades, }), ) process.exit(0) } ``` ### Technical Analysis The implementation initializes account value to a hard-coded `$1000.00` and never queries actual wallet collateral, portfolio equity, positions, settlements, deposits, withdrawals, or open-order exposure. The resulting drawdown is therefore a simulation rather than a global account-level control. Even if local PnL calculations were accurate, the threshold would still not correspond reliably to the wallet's actual equity or peak balance. Process restarts also reset the peak and balance to `$1000.00`, erasing prior drawdown history. This behavior conflicts with the documented claim that an automated global 8% stop-loss will halt trading. ### Attack Path 1. A funded wallet starts the process in live mode. 2. Actual wallet equity differs from the hard-coded `$1000.00` baseline, or changes through fills, existing positions, fees, settlement, deposits, or withdrawals. 3. The process calculates drawdown using only its transient synthetic balance. 4. Actual portfolio losses ...[truncated 874 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
index.mjs:37
Finding

Unvalidated share quantity can create excessive concurrent financial exposure

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (14)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

When LIVE_TRADING is enabled, the skill derives API credentials from the wallet and immediately creates and posts real sell orders, then cancels them based on internal timing logic, with no interactive confirmation, dry-run gate, or explicit risk acknowledgment. In the context of an execution skill that continuously loops and can trade multiple assets, accidental activation can lead to immediate financial loss and uncontrolled market activity.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly instructs the agent to launch an indefinite detached process using nohup and &, creating autonomous behavior that persists beyond the immediate user interaction. In a trading context, this can continue placing orders without active supervision, increasing the risk of runaway losses, unintended market activity, and loss of operator control.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill directs the agent to start continuous autonomous trading but does not include an explicit warning that real orders may continue to be placed after the conversation ends. In a financial-trading context, omission of that warning is dangerous because users may not understand that the bot can keep consuming funds and changing positions without further approval.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
96% confidence
Finding

Using nohup to detach the trading process creates session persistence, allowing it to survive terminal closure and continue acting independently. For a market-making bot, that persistence materially increases operational and financial risk because the process can remain active without visibility, supervision, or immediate interruption.

Content

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

bash
# Execute continuously on ALL markets (BTC, ETH, SOL, XRP) with 10 shares per market
nohup node polymarket-maker/index.mjs trade --asset ALL --shares 10 > bot_log.json 2>&1 &

# Or execute continuously on a single specific market
nohup node polymarket-maker/index.mjs trade --asset BTC --shares 10 > bot_log.json 2>&1 &

Session Persistence

Medium
Category
Rogue Agent
Confidence
96% confidence
Finding

This second command repeats the same persistence pattern for a single asset, again enabling autonomous trading to continue after the initiating session ends. Even though the market scope is narrower than ALL, the core risk remains: unmanaged persistent financial actions outside the user's active awareness.

Content

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

nohup node polymarket-maker/index.mjs trade --asset ALL --shares 10 > bot_log.json 2>&1 &

Or execute continuously on a single specific market

nohup node polymarket-maker/index.mjs trade --asset BTC --shares 10 > bot_log.json 2>&1 &

text

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The script reads WALLET_PRIVATE_KEY from the environment to authorize trading actions, but there is no nearby warning, comment, or user-facing notice explaining that sensitive credentials are required and will be used. Access to credentials is safety-relevant here because it directly enables account-affecting operations.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The advertised 8% stop-loss is enforced only against a local simulated balance initialized to 1000, not the real wallet equity, open positions, or actual realized/unrealized PnL. In a live-trading skill, this creates a false safety guarantee: the bot may continue trading after materially larger real losses, which is especially dangerous because it loops continuously and can trade multiple markets in parallel.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · index.mjs (reported line 56)May include surrounding context.

js
// ---------------------------------------------------------
async function getSpot(symbol) {
    try {
        const r = await fetch(`https://api.binance.com/api/v3/ticker/price?symbol=${symbol}`)
        return parseFloat((await r.json()).price)
    } catch {
        return null

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The documentation claims an automatic 8% stop-loss will halt trading, but this file provides no visible mechanism for validating that safeguard and simultaneously recommends detached execution with no active monitoring. That mismatch can mislead an operator into assuming risk controls exist and are functioning when the process may continue trading unchecked.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

Multiple comments and operational labels are written in French, such as risk-management and control-flow descriptions, with no indication that the skill is intentionally region-specific or that users may choose another language. This can violate language/locale policy when a skill implicitly assumes a single language without opt-in or justification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The inline documentation says the cycle runs for 'TOUS les actifs' and that Promise.all executes 'les 4 cryptos exactement en même temps'. In reality, ASSETS_TO_TRADE is derived from --asset and can contain a single asset or ALL, so the comment overstates and can contradict actual runtime behavior.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The dependency uses a caret range, allowing newer compatible versions of @polymarket/clob-client to be installed without explicit review. In a trading skill that interacts with external markets and likely handles funds or API credentials, an upstream compromise or breaking behavioral change could alter order logic or introduce malicious code into the execution path.

Content

Scanner excerpt · package.json (reported line 6)May include surrounding context.

json
"version": "1.0.0",
    "type": "module",
    "dependencies": {
        "@polymarket/clob-client": "^5.8.0",
        "dotenv": "^17.3.1",
        "ethers": "^6.16.0"
    }

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
88% confidence
Finding

The dotenv package is specified with a caret range, so future installs may resolve to a newer version that has not been validated. Although dotenv is less security-critical than a market client or signer library, it loads environment-based secrets and could become an attack vector if a compromised release exfiltrates configuration or credentials.

Content

Scanner excerpt · package.json (reported line 7)May include surrounding context.

json
"type": "module",
    "dependencies": {
        "@polymarket/clob-client": "^5.8.0",
        "dotenv": "^17.3.1",
        "ethers": "^6.16.0"
    }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The ethers dependency is unpinned via a caret range, which permits unreviewed updates to a core blockchain interaction library. Because this skill performs automated market making and likely signs transactions or manages wallet operations, a malicious or flawed upstream version could directly affect fund safety, transaction integrity, or signing behavior.

Content

Scanner excerpt · package.json (reported line 8)May include surrounding context.

json
"dependencies": {
        "@polymarket/clob-client": "^5.8.0",
        "dotenv": "^17.3.1",
        "ethers": "^6.16.0"
    }
}

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
index.mjs:12