Back to skill

Security audit

Polymarket Football Odds

Security checks for vulnerabilities and agentic risk

Overview

This skill is a purpose-aligned Polymarket soccer analysis helper, with a real but limited quota-exhaustion risk if users set an excessively large date range.

Install only if you are comfortable giving the skill an API-Football/API-SPORTS key and allowing requests to Polymarket Gamma and API-Football. Keep --days small, prefer --fixture-id when known, and treat the output as third-party model predictions plus market prices rather than an independent betting recommendation.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/analyze-polymarket-football.ts:256
Finding

Unbounded --days Option Enables Resource and API-Quota Exhaustion

Content
View full analysis
getFixturesByDate(apiKey, day))); fixtures = nested.flat(); } ``` ```ts function datesAround(date: string, days: number): string[] { const base = new Date(`${date}T12:00:00Z`); const results: string[] = []; for (let offset = -days; offset <= days; offset += 1) { const next = new Date(base); next.setUTCDate(base.getUTCDate() + offset); results.push(next.toISOString().slice(0, 10)); } return results; } ``` ### Technical Analysis The `--days` argument is checked only for decimal digits. It has no maximum value and is not validated with `Number.isSafeInteger()`. The supplied number controls the loop in `datesAround()`, which attempts to construct `2 × days + 1` date entries. Every generated date is subsequently converted into an authenticated API-Football request. All requests are started together through `Promise.all()`, with no concurrency limit, request budget, timeout, or early termination after a satisfactory fixture is found. Normal operation requires only a narrow date range—the documented default is one day on either side of the inferred date. Permitting an arbitrary range therefore exceeds the minimum network and API privileges needed for the declared fixture-matching functionality. ### Attack Path 1. An attacker or untrusted automation supplies a valid Polymarket input or slug and a very large argument, such as `--days 1000000`. 2. Argument parsing accepts the ...[truncated 1347 chars]
Remediation
View remediation
7 ) { throw new Error("--days must be an integer between 0 and 7."); } options.days = parsed; ``` 2. Apply the same validation inside the exported `analyzePolymarketFootball()` function. Library callers can bypass CLI parsing and currently supply an arbitrary `days` value directly. 3. Replace unbounded `Promise.all()` execution with sequential processing or a small concurrency pool. 4. Stop searching once a sufficiently confident fixture has been found rather than querying every date in the configured range. 5. Add request timeouts and a per-analysis request budget to prevent stalled or excessive third-party calls. 6. Add tests covering negative values, unsafe integers, extremely large values, and direct library calls that bypass command-line validation. ]]>
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The implementation largely aligns with the soccer/Polymarket analysis purpose: it accepts Polymarket URLs/slugs, extracts team names, queries API-Football, resolves a fixture, and returns 1X2-style prediction percentages with a human-readable summary. However, there are material description-behavior gaps. First, the description says it will calculate 1X2 probabilities, but the code simply fetches predictions.percent from API-Football and reports them; there is no independent probability calculation. Second, the description says it will compare with Polymarket implied odds, but the code only extracts and prints Polymarket outcome prices and never computes implied odds, normalizes them, or performs a comparison. Third, although obviously necessary for the workflow, the code actively calls Polymarket Gamma APIs, which are not reflected in the declared permissions/resources. This is not a totally different skill, but the missing comparison/calculation behavior is significant enough to count as a mismatch.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
API_FOOTBALL_KEY="..." node --experimental-strip-types scripts/analyze-polymarket-football.ts "https://polymarket.com/event/..."

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
API_FOOTBALL_KEY="..." node --experimental-strip-types scripts/analyze-polymarket-football.ts "https://polymarket.com/event/..."

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill requires environment access for an API key and network access to Polymarket/API-Football, but the manifest does not explicitly declare those capabilities. That creates a transparency and policy-enforcement gap: a reviewer or runtime may not realize the skill can exfiltrate user-provided URLs, make external requests, or depend on secrets from the environment.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/analyze-polymarket-football.ts:287

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/analyze-polymarket-football.ts:187