Back to skill

Security audit

Polymarket Trade Agent

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed Polymarket trading tool, but it handles a funded wallet private key and can place live orders without adequate safeguards.

Review carefully before installing. Use only a dedicated low-balance trading wallet, do not paste private keys into chats or shared terminals, remove the private-key prefix logging, add explicit trade confirmation or dry-run behavior, separate public market reads from authenticated trading, and use pinned audited dependencies.

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

T09 · Insecure Skill Coding Practices

Warning
Location
trade.py:80
Finding

Wallet Private-Key Prefix Disclosed in Console Output

Content
View full analysis

Vulnerability Details

File Location: trade.py:80-84
Vulnerability Type: Sensitive credential exposure through logging
Risk Level: Medium

Vulnerable Code

python
console.print(f"[cyan]Initializing ClobClient:[/cyan]")
console.print(f"  - Host: {host}")
console.print(f"  - Chain ID: {chain_id}")
console.print(f"  - Key (first 10 chars): {key[:10]}...")
console.print(f"  - Funder: {funder}")

Technical Analysis

The authenticated client initialization path prints the first ten characters of the configured wallet private key. Because a Polygon private key normally starts with 0x, this discloses eight hexadecimal digits of secret key material.

Private-key material must never be written to terminal output, logs, CI records, screenshots, or agent transcripts, even in truncated form. The disclosure occurs whenever get_client() is invoked, including through balance retrieval, market queries, and order operations.

This issue does not by itself disclose the complete private key, and brute-forcing the remaining key material would generally remain impractical. It nevertheless violates credential-handling requirements, permanently reveals part of a high-value signing secret, and can contribute to compromise when combined with another partial disclosure or weak key-generation process.

Attack Path

  1. The user configures POLYMARKET_PRIVATE_KEY.
  2. The user invokes a command that initializes ClobClient, such as polymarket balance, polymarket markets, polymarket buy, or polymarket sell.
  3. get_client() reads the private key from the environment.
  4. The code prints the first ten characters of the key to standard output.
  5. An attacker with access to terminal history, CI logs, captured agent output, support bundles, or screenshots obtains part of the wallet secret.
  6. The disclosed fragment may be correlated with other leaks or used to reduce the unknown key space if the key was ge ...[truncated 481 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove the private-key logging statement completely; do not replace it with another partial representation.
  • Log only a boolean status such as Private key configured: yes.
  • Avoid including credentials in exception messages, debug logs, telemetry, or returned objects.
  • Add automated secret-logging tests that capture console output and verify that no full or partial key value appears.
  • Review and purge accessible logs that may already contain private-key prefixes.
  • If other portions of the key may have been exposed elsewhere, rotate the wallet key and transfer assets to a newly generated wallet.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
trade.py:68
Finding

Public Market Queries Unnecessarily Initialize Wallet Signing Credentials

Content
View full analysis

Vulnerability Details

File Location: trade.py:68-101 and trade.py:137-149
Vulnerability Type: Violation of least privilege in read-only operations
Risk Level: Medium

Vulnerable Code

python
def get_client() -> Optional[ClobClient]:
    """Get authenticated Polymarket client"""
    key = get_private_key()
    funder = get_funder_address()
    if not key:
        return None
    
    try:
        host = "https://clob.polymarket.com"
        chain_id = 137  # Polygon
        
        console.print(f"[cyan]Initializing ClobClient:[/cyan]")
        console.print(f"  - Host: {host}")
        console.print(f"  - Chain ID: {chain_id}")
        console.print(f"  - Key (first 10 chars): {key[:10]}...")
        console.print(f"  - Funder: {funder}")
        
        # Create client with key and optional funder address
        signature_type = int(os.environ.get("POLYMARKET_SIGNATURE_TYPE", "1"))
        client = ClobClient(
            host,
            key=key,
            chain_id=chain_id,
            funder=funder,
            signature_type=signature_type
        )

        try:
            creds = client.create_or_derive_api_creds()
            client.set_api_creds(creds)
            console.print("[green]  - API credentials: derived successfully[/green]")
        except Exception as e:
            console.print(f"[red]Failed to derive API credentials: {e}[/red]")
            raise
        
        return client
python
def get_markets(limit: int = 10, search: str = None):
    """Get list of markets"""
    client = get_client()
    if not client:
        return None
    
    try:
        markets = client.get_markets(
            limit=limit,
            search=search,
        )
        return markets

Technical Analysis

get_markets() and the CLI market-search paths use get_client(), which reads the wallet pri ...[truncated 2029 chars]

Remediation
View remediation

Remediation Suggestions

  • Create separate authenticated and unauthenticated client constructors.
  • Use Polymarket's public API or an uncredentialed client for market lists, searches, market details, prices, and order books.
  • Load POLYMARKET_PRIVATE_KEY only immediately before an operation that genuinely requires authentication or signing.
  • Restrict API-credential derivation to authenticated account and trading operations.
  • Keep order construction and signing in a narrowly scoped module so public research commands cannot access wallet secrets.
  • Add tests asserting that market discovery works without POLYMARKET_PRIVATE_KEY and never calls get_private_key() or API-credential derivation.
  • Consider isolating signing in a hardware wallet or dedicated signer rather than retaining an unrestricted raw private key in the general CLI process.

T08 · Insecure Dependencies

Note
Location
pyproject.toml:1
Finding

Runtime and Build Dependencies Are Not Reproducibly Pinned

Content
View full analysis

Vulnerability Details

File Location: pyproject.toml:1-16 and requirements.txt:1-7
Vulnerability Type: Unbounded dependency resolution and inconsistent manifests
Risk Level: Low

Vulnerable Code

toml
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "polymarket-trade-agent"
version = "0.2.0"
description = "Polymarket trading agent with complete implementation"
readme = "SKILL.md"
requires-python = ">=3.9"
dependencies = [
    "py-clob-client>=0.34.0",
    "requests>=2.28.0",
    "rich>=13.0.0",
    "typer>=0.9.0",
    "eth-account>=0.9.0",
    "web3>=6.0.0",
]
text
py-clob-client>=0.34.0
requests>=2.28.0
rich>=13.0.0
typer>=0.9.0
eth-account>=0.9.0
web3>=6.0.0
python-dotenv>=1.0.0

Technical Analysis

The project specifies only minimum versions and does not impose upper bounds, use a reviewed lock file, or provide integrity hashes. Consequently, installations performed at different times can resolve to materially different direct and transitive dependency versions.

This is particularly sensitive because py-clob-client receives the wallet private key and participates in credential derivation and order signing. A malicious or compromised future release selected by the resolver could execute in the process and inspect environment variables, function arguments, or signing operations.

The dependency manifests are also inconsistent: python-dotenv appears in requirements.txt but not in pyproject.toml. This makes the installed dependency set vary according to the installation method. The audit did not identify a currently malicious package or typosquatted dependency; the confirmed weakness is the absence of reproducible dependency controls.

Attack Path

  1. A user or deployment system installs the project at a later date using the unbounded version constraints.
  2. The package ...[truncated 1224 chars]
Remediation
View remediation

Remediation Suggestions

  • Generate and commit a reviewed lock file containing exact versions for direct and transitive dependencies.
  • Use integrity hashes for deployment installations, such as a hash-locked requirements file.
  • Pin or tightly constrain build-system dependencies as well as runtime dependencies.
  • Reconcile pyproject.toml and requirements.txt so all supported installation methods produce the same dependency set.
  • Remove python-dotenv if unused, or declare it consistently if it is required.
  • Use automated dependency vulnerability scanning and controlled update pull requests.
  • Review changes to security-sensitive packages, especially py-clob-client, eth-account, and web3, before updating the lock file.
  • Install from the official package index through a trusted, TLS-protected configuration and avoid unreviewed alternate indexes.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (21)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill instructs users to obtain and export a wallet private key that controls a funded Polymarket account, but it does not include clear guidance that this is a highly sensitive secret whose disclosure can lead to total account compromise. Because the key is tied to real funds and trading authority, unsafe handling in shell history, logs, screenshots, or shared environments could enable theft or unauthorized trading.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill exposes direct buy and sell commands for a real-money prediction market but does not clearly warn that these actions can place irreversible live orders using the user's funded wallet. In this context, an agent or user could mistake the commands for simulation or low-risk analysis tooling and unintentionally execute trades, causing immediate financial loss.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The setup instructions explicitly tell users to export a raw private key directly into an environment variable and even show an inline shell command containing the secret. This encourages unsafe key handling: secrets may be exposed via shell history, process/environment inspection, logs, screenshots, or copied terminal transcripts, and in this trading context compromise of the key can directly lead to theft of funds and unauthorized trades.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The function can submit real market orders immediately using live credentials from environment variables, with no confirmation, dry-run mode, bounds checking, or explicit acknowledgement that funds are at risk. In an agent-skill context, this is more dangerous because higher-level automation or prompt-influenced calls could trigger unintended trades and cause direct financial loss.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: setuptools has 10 known advisory(ies) (CVE-2013-1633 (Setuptools vulnerable to Man-in-the-middle attacks); CVE-2025-47273 (setuptools has a path traversal vulnerability in PackageIndex.download that lead); CVE-2024-6345 (setuptools vulnerable to Command Injection via package URL) +7 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding

wheel is declared without an exact version, so the build process may use a release with known advisories depending on the environment. This primarily affects packaging/build integrity rather than direct runtime behavior, but it still represents an avoidable supply-chain weakness.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: wheel has 4 known advisory(ies) (CVE-2026-24049 (Wheel Affected by Arbitrary File Permission Modification via Path Traversal in w); CVE-2022-40898 (pypa/wheel vulnerable to Regular Expression denial of service (ReDoS)); CVE-2022-40898 (An issue discovered in Python Packaging Authority (PyPA) Wheel 0.37.1 and earlie) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding

wheel is declared without an exact version, so the build process may use a release with known advisories depending on the environment. This primarily affects packaging/build integrity rather than direct runtime behavior, but it still represents an avoidable supply-chain weakness.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The dependency on requests is specified with only a minimum version (>=2.28.0) rather than a pinned or tightly constrained version, so builds are not reproducible and may resolve to versions with known advisories depending on installer behavior, mirrors, or lock state. In a trading agent, outbound HTTP handling can be security-sensitive, so leaving a broadly ranged dependency unverifiable increases supply-chain and runtime risk.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: eth-account has 2 known advisory(ies) (CVE-2022-1930 (Regular expression denial of service in eth-account); CVE-2022-1930 (Regular expression denial of service in eth-account)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding

eth-account is not pinned to an exact safe version, making it impossible to verify from this manifest alone whether installations will avoid known vulnerable releases. Because this package handles Ethereum account operations, even low-likelihood dependency weakness is more relevant in a financial/trading context than it would be in a non-sensitive utility.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: web3 has 2 known advisory(ies) (CVE-2026-40072 (web3.py: SSRF via CCIP Read (EIP-3668) OffchainLookup URL handling); CVE-2026-40072 (web3.py: SSRF via CCIP Read (EIP-3668) OffchainLookup URL handling)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
90% confidence
Finding

The web3 dependency is only minimum-bounded and not pinned, so consumers may install a version affected by known security issues, including network-interaction flaws such as SSRF-related behavior in some releases. In a blockchain trading agent that may process remote chain data and perform external requests, this context makes an unverifiable web3 version more dangerous than in a simple offline application.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified with a lower bound only, which allows future unreviewed versions to be installed and makes builds non-reproducible. In a security-sensitive skill that interacts with blockchain libraries, this increases supply-chain risk because a compromised or incompatible upstream release could be pulled in silently.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
py-clob-client>=0.34.0
requests>=2.28.0
rich>=13.0.0
typer>=0.9.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

Using requests>=2.28.0 without an upper bound or exact pin permits installation of unknown future releases and prevents reliable verification against known advisories. Because requests has a history of security issues, leaving it unpinned makes it harder to ensure deployments are not exposed to vulnerable versions.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
py-clob-client>=0.34.0
requests>=2.28.0
rich>=13.0.0
typer>=0.9.0
eth-account>=0.9.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The manifest does not pin requests, so it is impossible to determine whether deployed environments use a version affected by known advisories. Because requests is a core HTTP client and often processes attacker-controlled URLs or redirects, unresolved version ambiguity can expose the skill to real network-originated attacks.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The rich package is unpinned, so installations may resolve to different versions over time, including versions not tested by the skill author. This is primarily a supply-chain and reproducibility weakness rather than an immediate exploitable flaw in the file itself.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
py-clob-client>=0.34.0
requests>=2.28.0
rich>=13.0.0
typer>=0.9.0
eth-account>=0.9.0
web3>=6.0.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

An unpinned typer dependency allows uncontrolled version drift and can introduce breaking or malicious upstream changes into the environment. While the direct impact is limited from this file alone, it weakens build integrity and change control.

Content

Scanner excerpt · requirements.txt (reported line 4)May include surrounding context.

text
py-clob-client>=0.34.0
requests>=2.28.0
rich>=13.0.0
typer>=0.9.0
eth-account>=0.9.0
web3>=6.0.0
python-dotenv>=1.0.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

eth-account is unpinned, so the environment may install versions with known or future vulnerabilities, and the project cannot prove which release is actually used. Since this library handles Ethereum account operations, dependency uncertainty is more dangerous than for a purely cosmetic package because it may affect credential or signing-related behavior.

Content

Scanner excerpt · requirements.txt (reported line 5)May include surrounding context.

text
requests>=2.28.0
rich>=13.0.0
typer>=0.9.0
eth-account>=0.9.0
web3>=6.0.0
python-dotenv>=1.0.0

Unverifiable Dependency: eth-account has 2 known advisory(ies) (CVE-2022-1930 (Regular expression denial of service in eth-account); CVE-2022-1930 (Regular expression denial of service in eth-account)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding

eth-account has known advisories, but the unpinned requirement prevents verification that the installed version is safe. In a skill that includes Ethereum account tooling, this ambiguity is more concerning because vulnerable parsing or account-handling code could affect availability or security-sensitive wallet operations.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

web3>=6.0.0 allows unreviewed versions of a network-facing blockchain library to be installed, creating supply-chain and security exposure. In this context, the risk is elevated because web3 may interact with remote endpoints and has advisories associated with request-handling behaviors such as SSRF-related issues.

Content

Scanner excerpt · requirements.txt (reported line 6)May include surrounding context.

text
rich>=13.0.0
typer>=0.9.0
eth-account>=0.9.0
web3>=6.0.0
python-dotenv>=1.0.0

Unverifiable Dependency: web3 has 2 known advisory(ies) (CVE-2026-40072 (web3.py: SSRF via CCIP Read (EIP-3668) OffchainLookup URL handling); CVE-2026-40072 (web3.py: SSRF via CCIP Read (EIP-3668) OffchainLookup URL handling)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
96% confidence
Finding

web3 has known advisories and the requirement is unpinned, so the deployed package could be a vulnerable release without any way to verify from this manifest. Given web3's role as a network-facing blockchain client and the cited SSRF-related advisory, this skill context makes the issue more dangerous than a generic dependency hygiene problem.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

python-dotenv is unpinned, allowing installations to drift to versions that may contain file-handling or environment-loading vulnerabilities. Because dotenv tooling often touches local configuration and secrets, uncertainty around its version can have greater impact than a generic utility package.

Content

Scanner excerpt · requirements.txt (reported line 7)May include surrounding context.

text
typer>=0.9.0
eth-account>=0.9.0
web3>=6.0.0
python-dotenv>=1.0.0

Unverifiable Dependency: python-dotenv has 2 known advisory(ies) (CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via ); CVE-2026-28684 (python-dotenv reads key-value pairs from a .env file and can set them as environ)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding

python-dotenv has known advisories, and because the requirement is not pinned there is no assurance that a safe version will be installed. Since dotenv libraries can read or modify local configuration files and environment variables, vulnerable versions may contribute to secret exposure or unsafe file operations.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The function signature and docstring suggest caller control over whether closed positions are included, but include_closed is never used in the implementation. This is an intent/documentation mismatch because the documented behavior contradicts the actual code path.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.