Back to skill

Security audit

Polymarket Cli

Security checks for vulnerabilities and agentic risk

Overview

The skill is a read-only Polymarket data CLI, but its install instructions ask users to download and run an unpinned Python file from a mutable GitHub branch.

Install from the bundled reviewed polymarket_cli.py or a pinned release with a published hash, not by curling the mutable main-branch URL. The CLI itself appears read-only, but avoid running the included verification harness on untrusted folders outside a sandbox.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

T03 · Remote Payload Retrieval and Execution

Warning
Location
SKILL.md:32
Finding

Mutable Remote Executable Retrieved Without Integrity Verification

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:32-41; duplicated in README.md:34-43
Vulnerability Type: Remote payload retrieval and execution
Risk Level: Medium

Complete Code Snippet:

bash
## Install

# Requires Python 3.8+. No pip install needed.
curl -O https://raw.githubusercontent.com/itsPremkumar/polymarket-cli/main/polymarket_cli.py
# Or copy the file anywhere — it's self-contained.

## Quick start

python polymarket_cli.py --help        # list options

Technical Analysis

The documented installation process downloads a Python executable from the mutable main branch of a personal GitHub repository and subsequently instructs the user to execute it. The command does not pin the download to a reviewed commit or immutable release and performs no checksum or signature verification.

Consequently, the code ultimately executed by users can differ from the version included in and reviewed with this Skill package. HTTPS protects the connection in transit but does not protect users against repository compromise, maintainer account takeover, malicious upstream changes, or an unsafe future update.

Retrieving live public market data is necessary for the declared functionality, but retrieving a replacement executable is not necessary because an audited copy of polymarket_cli.py is already bundled in the project. This installation method therefore exceeds the minimum network access required for the Skill.

No evidence was found that the currently bundled script contains a malicious payload. The risk arises from allowing the effective executable payload to change after review.

Attack Path

  1. An attacker compromises the upstream maintainer account or obtains write access to itsPremkumar/polymarket-cli.
  2. The attacker replaces or modifies polymarket_cli.py on the main branch.
  3. A user follows the installation instructions and downloads the attacker-controlled version through the ...[truncated 838 chars]
Remediation
View remediation

Remediation Suggestions

  1. Prefer execution of the audited polymarket_cli.py already bundled with the Skill rather than downloading another copy.
  2. If remote installation must remain supported, pin the URL to a reviewed commit hash or an immutable, versioned release artifact instead of main.
  3. Publish a SHA-256 digest through an independently protected release channel and require users to verify it before execution.
  4. Consider signing release artifacts and documenting signature verification using a maintained signing key.
  5. Update both SKILL.md and README.md so their installation instructions remain consistent.
  6. Add CI checks that reject executable download URLs referencing mutable branches and require integrity metadata for remote artifacts.
  7. Clearly disclose the exact network destinations used at runtime. The bundled program otherwise appears limited to read-only HTTPS requests to the fixed Polymarket API origin.
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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 (4)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

This code executes arbitrary Python files found in the target product folder as part of verification by invoking python <file> self-test. In an adversarial or untrusted repository, a product author can place malicious code in a .py file and have it run automatically during CI or local verification, resulting in arbitrary code execution.

Content

Scanner excerpt · ci/verify_product.py (reported line 37)May include surrounding context.

python
def has_self_test(fp):
    r = subprocess.run([sys.executable, fp, "self-test"], capture_output=True, text=True, timeout=30)
    return r.returncode == 0 and "PASS" in r.stdout

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · ci/verify_product.py (reported line 67)May include surrounding context.

python
all_ok &= axis(False, "frontmatter (no SKILL.md)")
        all_ok &= axis(False, "docs (no SKILL.md)")
    # 3 compiles
    comp_ok = all(subprocess.run([sys.executable, "-m", "py_compile", fp],
                                capture_output=True).returncode == 0 for fp in files)
    all_ok &= axis(comp_ok, "compiles (py_compile all .py)")
    # 4 self-test (any of 3 valid forms)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
99% confidence
Finding

This code directly executes any test_*.py or *_test.py file in the target folder. In the context of a verifier for potentially untrusted skills/products, this is especially dangerous because malicious contributors can embed arbitrary code in test files and obtain code execution in CI or on a reviewer’s machine.

Content

Scanner excerpt · ci/verify_product.py (reported line 79)May include surrounding context.

python
tests = [os.path.join(folder, f) for f in os.listdir(folder)
                 if (f.startswith("test_") or f.endswith("_test.py")) and f.endswith(".py")]
        if tests:
            st_ok = all(subprocess.run([sys.executable, t], capture_output=True, text=True,
                                      timeout=30).returncode == 0 for t in tests)
            st_note = f"{len(tests)} test_*.py"
        elif re.search(r"(?im)^test\s*:", skill_txt):

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · ci/verify_product.py (reported line 92)May include surrounding context.

python
# 7 deploy-ready
    ci = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ci_check.py")
    if os.path.isfile(ci) and os.path.isfile(skill):
        r = subprocess.run([sys.executable, ci], cwd=folder, capture_output=True, text=True)
        all_ok &= axis(r.returncode == 0, "deploy-ready (ci/ci_check.py PASS)")
    else:
        all_ok &= axis(True, "deploy-ready (skipped)")