Back to skill

Security audit

Polymarket Edge Trader

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed Polymarket trading automation skill, but it has review-worthy financial safety gaps around dry-run behavior, scheduled execution, endpoint trust, and an unpinned SDK handling credentials and signed orders.

Review this before installing. Use it only in an isolated environment with narrowly scoped AION credentials, do not provide signed orders unless you intend live trading, avoid custom AION_BASE_URL values unless you fully trust the endpoint, and treat even dry-run or scheduled runs as potentially capable of auto-redeeming positions.

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

T08 · Insecure Dependencies

Error
Location
SKILL.md:20
Finding
Unpinned Third-Party SDK Controls Credential and Financial Operations<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:20-24`, `clawhub.json:4-7`, `edge_trader.py:17`, `edge_trader.py:44-53` **Vulnerability Type**: Unpinned security-critical dependency and unsafe supply-chain trust **Risk Level**: High ### Vulnerable Code ```markdown Install the AION SDK: ```bash pip install aionmarket-sdk ``` ``` ```json "requires": { "pip": ["aionmarket-sdk"], "env": ["AION_API_KEY"] } ``` ```python from aion_sdk import AionMarketClient ``` ```python def get_client() -> AionMarketClient: """Get or create AionMarketClient singleton.""" global _client if _client is None: api_key = os.getenv("AION_API_KEY") if not api_key: raise ValueError("AION_API_KEY environment variable is required") base_url = os.getenv("AION_BASE_URL", "https://pm-t1.bxingupdate.com/bvapi") _client = AionMarketClient(api_key=api_key, base_url=base_url) return _client ``` ### Technical Analysis The Skill installs `aionmarket-sdk` without an exact version, package hash, or verified source declaration. The imported SDK controls all network and financial operations, including access to the AION API key, account briefing, redemption, market context, and signed-order submission. Because dependency resolution is not reproducible, a compromised future package version or package-registry incident could introduce arbitrary installation-time or runtime code after the Skill itself has been reviewed. The default service endpoint is also not an evident official Polymarket origin, while the project provides no local SDK implementation or integrity mechanism with which to validate the behavior of that dependency. ### Attack Path 1. An attacker compromises the package publisher, registry account, distribution infrastructure, or a newly resolved package release. 2. The user follows the documented `pip install aionmarket-sdk` command without a version or hash constraint. 3. Malicious dependency code execut ...[truncated 816 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `aionmarket-sdk` to an audited exact version in both installation documentation and package metadata. 2. Use a lock file or requirements file containing cryptographic package hashes, such as `pip install --require-hashes`. 3. Document and verify the expected package registry, publisher identity, source repository, and release-signing process. 4. Audit or vendor the security-critical portions of the SDK responsible for authentication, redemption, and order submission. 5. Run the Skill in a restricted environment containing only the environment variables and filesystem permissions it requires. 6. Use a verified service endpoint and document its ownership and trust relationship. 7. Add dependency monitoring and require manual security review before updating the pinned SDK version. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
edge_trader.py:94
Finding
Dry-Run Mode Performs Potentially State-Changing Auto-Redemption<![CDATA[ ## Vulnerability Details **File Location**: `edge_trader.py:94-111`, `edge_trader.py:389-400` **Vulnerability Type**: Missing authorization boundary for state-changing financial operation **Risk Level**: Medium ### Vulnerable Code ```python def auto_redeem_if_possible() -> None: """Auto-redeem resolved markets per AION best practices.""" try: client = get_client() results = client.auto_redeem() except Exception as exc: print(f"Auto-redeem skipped: {exc}") return if not isinstance(results, list): return redeemed = [r for r in results if r.get("success")] if redeemed: for item in redeemed: market_id = item.get("market_id") tx_hash = item.get("tx_hash") print(f"Redeemed {market_id}: tx={tx_hash}") ``` ```python def run_once(args: argparse.Namespace) -> int: """Execute one trading cycle.""" try: client = get_client() except ValueError as exc: print(f"Client error: {exc}") return 1 # Auto-redeem any claimable positions auto_redeem_if_possible() ``` ### Technical Analysis `run_once()` invokes `auto_redeem_if_possible()` before any check of `args.live`. Consequently, the documented default dry-run path calls `client.auto_redeem()` even though dry-run mode is presented as not submitting live orders. Redemption can be a state-changing financial or blockchain operation. Depending on the SDK and account configuration, it may claim positions, submit transactions, incur fees, invoke signing behavior, or alter account state. Although auto-redemption is disclosed as a feature, it is not protected by the explicit `--live` consent boundary that protects trade submission. Daemon mode magnifies the issue by repeating the redemption attempt every polling cycle. ### Attack Path 1. A user configures the required AION credentials and runs the Skill without `--live`, expecting simulation-only behavior. ...[truncated 757 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Gate `auto_redeem_if_possible()` behind `args.live` or a dedicated explicit `--redeem` flag. 2. Make the default dry-run path strictly read-only. 3. In dry-run mode, query and display redeemable positions without invoking the state-changing redemption method. 4. Require clear confirmation before the first redemption in interactive use. 5. Document whether redemption submits blockchain transactions, uses signatures, or incurs fees. 6. Add tests proving that neither `client.trade()` nor `client.auto_redeem()` is called unless the corresponding live-action flag is present. 7. Consider disabling automatic redemption in daemon mode unless it is separately authorized in configuration. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
edge_trader.py:499
Finding
Complete Signed Financial Orders Can Be Sent to an Arbitrary Configurable Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `edge_trader.py:44-53`, `edge_trader.py:499-544` **Vulnerability Type**: Insufficient destination validation for sensitive financial payloads **Risk Level**: Medium ### Vulnerable Code ```python def get_client() -> AionMarketClient: """Get or create AionMarketClient singleton.""" global _client if _client is None: api_key = os.getenv("AION_API_KEY") if not api_key: raise ValueError("AION_API_KEY environment variable is required") base_url = os.getenv("AION_BASE_URL", "https://pm-t1.bxingupdate.com/bvapi") _client = AionMarketClient(api_key=api_key, base_url=base_url) return _client ``` ```python signed_order_json = os.getenv("AION_SIGNED_ORDER_JSON", "").strip() if not signed_order_json: decisions.append("SKIP: --live requires AION_SIGNED_ORDER_JSON") print_operator_summary(risk_alerts, decisions, order_updates) return 1 try: order_payload = json.loads(signed_order_json) except json.JSONDecodeError as exc: decisions.append(f"SKIP: Invalid AION_SIGNED_ORDER_JSON: {exc}") print_operator_summary(risk_alerts, decisions, order_updates) return 1 condition_id = get_condition_id(best["market"]) if not condition_id: decisions.append("SKIP: No condition ID for trade payload") print_operator_summary(risk_alerts, decisions, order_updates) return 1 payload = { "venue": VENUE, "marketConditionId": condition_id, "marketQuestion": get_question(best["market"]), "outcome": best["side"], "orderSize": round(amount_usd, 2), "price": round(best["yes_price"], 4), "isLimitOrder": True, "orderType": "GTC", "walletAddress": wallet_address, "reasoning": reasoning, "source": TRADE_SOURCE, "skill_slug": SKILL_SLUG, "order": order_payload, } try: result = client.trade(payload) except Exception as exc: decisions.append(f"SKIP: Trade submission failed: {exc}") print_operat ...[truncated 2351 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Allowlist verified HTTPS API origins and reject all other schemes and hosts by default. 2. Require a separate explicit unsafe-override flag when using a custom endpoint. 3. Display the final destination hostname and require confirmation before sending a signed order to a nondefault service. 4. Validate TLS certificates normally and do not permit plaintext HTTP for credentials or signed orders. 5. Minimize signature validity periods and bind every signature tightly to the intended chain, verifying contract, token, side, amount, nonce, expiration, and taker restrictions. 6. Prefer direct submission to the intended trading venue when feasible rather than relaying reusable signed orders through an intermediary. 7. Provide narrowly scoped API keys and rotation/revocation procedures. 8. Ensure signed payloads and authentication headers are never written to logs, exception output, telemetry, or crash reports. 9. Document exactly which fields leave the local system and identify the organization operating the receiving endpoint. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill references environment-based secrets and operational inputs such as AION_API_KEY, WALLET_PRIVATE_KEY, WALLET_ADDRESS, and AION_SIGNED_ORDER_JSON, but it does not declare an explicit tool scope or permission boundary. In an agent ecosystem, missing scope declarations can cause the runtime to grant broader environment access than operators expect, increasing the chance that sensitive trading credentials are exposed or misused by the skill or adjacent components.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The manifest explicitly supports live order submission via wallet-linked context and a pre-signed order payload, but it does not clearly warn users that the skill can place real trades involving real funds and potentially irreversible financial loss. In a trading automation skill, omission of a prominent risk disclosure increases the chance of accidental enablement, unsafe credential provisioning, or users misunderstanding dry-run versus live-trading behavior.

Static analysis

No suspicious patterns detected.