Back to skill

Security audit

Polymarket Arb Scanner Pro

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real trading tool, but its safety claims do not match its sequential order execution and could leave a user with unexpected financial exposure.

Review this carefully before installing. Use a dedicated low-balance wallet only, do not rely on the stated 'no position taken' or 'risk-free' guarantees, and avoid live --buy execution unless the order handling is fixed to detect, report, and manage partial execution. Pin and review dependencies before running with private-key access.

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)

T09 · Insecure Skill Coding Practices

Error
Location
arb_scanner.py:103
Finding

Sequential FOK Orders Do Not Provide Atomic Arbitrage Execution

Content
View full analysis

Vulnerability Details

File Location: arb_scanner.py:103-126, arb_scanner.py:211-220; contradictory guarantees in SKILL.md:13 and SKILL.md:55-57
Vulnerability Type: Non-atomic financial transaction and inaccurate failure handling
Risk Level: High

Vulnerable Code

python
def execute_arb(client, arb, deploy_usd):
    """
    Execute both legs as Fill-or-Kill.
    Both must fill or neither does — no leg risk.
    """
    from py_clob_client.clob_types import MarketOrderArgs, OrderType

    yes_amount = deploy_usd * arb["yes_price"] / (arb["yes_price"] + arb["no_price"])
    no_amount  = deploy_usd * arb["no_price"]  / (arb["yes_price"] + arb["no_price"])

    results = []
    for token_id, amount, label in [
        (arb["yes_token"], yes_amount, "YES"),
        (arb["no_token"],  no_amount,  "NO"),
    ]:
        try:
            args  = MarketOrderArgs(token_id=token_id, amount=amount, side="BUY")
            order = client.create_market_order(args)
            resp  = client.post_order(order, OrderType.FOK)
            status = resp.get("status", "?")
            filled = resp.get("success", False) or status == "matched"
            results.append({"label": label, "filled": filled, "status": status, "resp": resp})
        except Exception as e:
            results.append({"label": label, "filled": False, "status": "error", "error": str(e)})

    all_filled = all(r["filled"] for r in results)
    return all_filled, results

The resulting failure is reported as safe:

python
ok, results = execute_arb(client, arb, deploy)
for r in results:
    status = "✅" if r["filled"] else "❌"
    print(f"     {status} {r['label']} — {r['status']}")

if ok:
    print(f"     🎉 Both legs filled! Locked in ${profit:.2f} profit at resolution")
    executed += 1
    if rm:
        rm.record_order()
        rm.record_order()  # two orders (YES + NO)
        rm.re
...[truncated 2467 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove all claims that independent FOK orders are simultaneous or atomic unless the exchange provides an atomic batch-order facility with guaranteed all-or-none behavior.
  2. Use an exchange-supported atomic or batch transaction mechanism if one is available and verify its actual rollback semantics.
  3. Immediately re-read executable order-book prices and available quantities before submitting either leg. Do not rely solely on outcomePrices from the market metadata API.
  4. After each submission, distinguish among filled, partially filled, rejected, and indeterminate states using authoritative exchange responses.
  5. If the first leg fills and the hedge fails, initiate a bounded emergency unwind or hedge procedure. Apply explicit maximum-loss and slippage limits.
  6. Report partial execution prominently, including the token, amount, execution price, and required operator action. Never print “no position taken” unless account state confirms that assertion.
  7. Record each successful order and position independently in the risk manager, even when the paired trade fails.
  8. Reserve sufficient capital for emergency unwinds and stop further opportunities after any partial execution until the account is reconciled.
  9. Add integration tests covering first-leg success followed by second-leg rejection, timeout, exception, and stale or ambiguous exchange responses.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:29
Finding

Wallet-Capable Third-Party Dependencies Are Installed Without Version or Integrity Pinning

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:29-31 and SKILL.md:88-90
Vulnerability Type: Unpinned third-party dependency installation
Risk Level: Medium

Vulnerable Instructions

markdown
## Setup

```bash
pip install requests
text

The requirements section separately instructs:

```markdown
## Requirements

- Python 3.9+
- `py_clob_client`: `pip install polymarket-clob-client`
- Polymarket wallet with USDC on Polygon

Technical Analysis

Both installation commands resolve the latest package versions available from the environment's default Python package index. The instructions provide no version constraints, lock file, package hashes, or verified repository source.

This is especially sensitive for polymarket-clob-client, which is imported in the same process that reads PRIVATE_KEY and constructs authenticated trading orders. Any imported Python package executes with the process's effective operating-system permissions and can read its environment variables.

The implementation does not import requests; therefore, directing users to install it unnecessarily expands the dependency and supply-chain attack surface.

This finding does not establish that either named package is currently malicious. The vulnerability is the absence of reproducible and integrity-verified dependency resolution for software that operates with wallet authority.

Attack Path

  1. A user follows the documented installation commands.
  2. pip resolves whatever package release is current on the configured package index at installation time.
  3. A compromised package release, compromised maintainer account, unsafe transitive dependency, or future malicious update is downloaded.
  4. Package-controlled code executes during installation or when arb_scanner.py imports the client.
  5. The dependency reads PRIVATE_KEY or WALLET_ADDRESS from the process environment, modifies generated orders, ...[truncated 738 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the requests installation instruction because the implementation does not use that package.
  2. Pin polymarket-clob-client and every transitive dependency to reviewed versions in a lock file.
  3. Use hash-verified installation, such as a requirements file containing exact versions and --hash entries, and install with pip --require-hashes.
  4. Document the verified official package source and expected package name to reduce dependency-confusion and typosquatting risk.
  5. Review dependency updates before changing locked versions rather than resolving the newest release during every installation.
  6. Run the scanner in an isolated virtual environment or container under a dedicated, unprivileged operating-system account.
  7. Use a wallet dedicated to this function with narrowly limited funds and allowances. Avoid exposing unrelated wallet assets to the dependency process.
  8. Where supported, replace direct long-lived private-key access with constrained signing or delegated credentials that cannot authorize unrelated transactions.
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · arb_scanner.py (reported line 29)May include surrounding context.

python
CLOB_HOST    = "https://clob.polymarket.com"

def load_env():
    env_path = Path(__file__).parent / ".env"
    if env_path.exists():
        for line in env_path.read_text().splitlines():
            line = line.strip()

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The function claims atomic all-or-nothing behavior, but it places the YES and NO FOK orders one after the other. If the first leg fills and the second fails due to price movement, liquidity changes, or API error, the wallet can be left with unintended directional exposure rather than a locked-in arbitrage. In a live trading skill that can place real orders, this mismatch between documented safety guarantees and actual behavior is materially dangerous.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code prints 'no position taken (safe)' whenever both legs were not reported as filled, but it never verifies that zero legs filled. Because execution is sequential, one leg may have filled while the other failed, causing the operator or downstream automation to believe there is no exposure when there may be an open position requiring immediate action. In a trading automation context, misleading safety status increases the chance of unnoticed loss.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.