Back to skill

Security audit

prediction-markets-research

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent, but its API helper is broader than its documented read-only market-data purpose requires.

Review before installing. The skill appears intended for prediction-market research and does not show hidden persistence or credential theft, but only use it if you are comfortable giving an agent access to a Crawlora API key and sending market-search queries or JSON bodies to Crawlora. The helper should be tightened to exact route patterns and documented HTTP methods before being treated as well-scoped.

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/crawlora.sh:45
Finding
Route Allowlist and HTTP Method Validation Bypass## Vulnerability Details **File Location**: `scripts/crawlora.sh`, lines 45-113 **Vulnerability Type**: Permissive route matching and method authorization **Risk Level**: Medium ### Vulnerable Code ```bash # This skill's helper is limited to its documented Crawlora route set. Keep # caller-account surfaces and unrelated API routes out of the helper even if # someone supplies an undocumented path directly. case "$method" in GET|POST) ;; *) echo "only GET and POST are supported by the prediction-markets-research skill" >&2 exit 2 ;; esac # Reject path syntax that could smuggle a route through a shell glob check. case "$path" in ""|*[?#%]*|*..*|*//* ) echo "invalid path for the prediction-markets-research skill" >&2 exit 2 ;; esac case "$path" in /kalshi/event/*) ;; /kalshi/event/*/history) ;; /kalshi/event/*/metadata) ;; /kalshi/events) ;; /kalshi/events/multivariate) ;; /kalshi/exchange/schedule) ;; /kalshi/exchange/status) ;; /kalshi/historical/cutoff) ;; /kalshi/historical/market/*) ;; /kalshi/historical/market/*/history) ;; /kalshi/historical/markets) ;; /kalshi/historical/trades) ;; /kalshi/market/*) ;; /kalshi/market/*/history) ;; /kalshi/market/*/orderbook) ;; /kalshi/markets) ;; /kalshi/markets/history) ;; /kalshi/markets/orderbooks) ;; /kalshi/series) ;; /kalshi/series/*) ;; /kalshi/trades) ;; /metaculus/category/*/questions) ;; /metaculus/comments-feed) ;; /metaculus/project/*/questions) ;; /metaculus/question/*) ;; /metaculus/question/*/forecast-history) ;; /metaculus/question/*/forecasts) ;; /metaculus/question/*/metadata) ;; /metaculus/question/*/options) ;; /metaculus/questions) ;; /metaculus/top-comments) ;; /metaculus/tournament/*/questions) ;; /polymarket/activity/trades) ;; /polymarket/clob/market/*) ;; /polymarket/dashboards/macro ...[truncated 3676 chars]
Remediation
## Remediation Suggestions 1. Replace the independent method and path checks with a single route table that binds each endpoint shape to its permitted HTTP method. 2. Validate every path parameter as exactly one nonempty segment using an explicit character allowlist appropriate to that parameter, such as identifiers, numeric IDs, slugs, or tickers. 3. Reject slash characters inside path parameters instead of relying on unrestricted shell `*` patterns. 4. Permit `POST` only for the four documented batch endpoints: - `/polymarket/tokens/midpoints` - `/polymarket/tokens/orderbooks` - `/polymarket/tokens/prices` - `/polymarket/tokens/spreads` 5. Permit only `GET` for all endpoints documented as read-only GET routes. 6. Use anchored regular expressions or explicit parsing. For example: ```bash if [[ "$method" == "GET" && "$path" =~ ^/kalshi/market/[A-Za-z0-9._-]+$ ]]; then : elif [[ "$method" == "GET" && "$path" =~ ^/kalshi/market/[A-Za-z0-9._-]+/(history|orderbook)$ ]]; then : elif [[ "$method" == "POST" && "$path" =~ ^/polymarket/tokens/(midpoints|orderbooks|prices|spreads)$ ]]; then : else echo "unsupported route or HTTP method" >&2 exit 2 fi ``` 7. Add negative tests for nested paths, method mismatches, encoded separators, empty parameters, and undocumented suffixes. 8. Retain the fixed HTTPS base URL, restricted API-key alphabet, private temporary configuration file, and stdin-based POST body handling, as these controls appropriately reduce credential leakage and local-file disclosure risks.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (9)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill invokes shell commands via `scripts/crawlora.sh` but does not declare any explicit tool restrictions such as `allowed-tools` or `permissions`. That creates an avoidable trust gap: an agent may permit broader shell capability than is actually needed, increasing the chance of unintended command execution or misuse if later edits add unsafe shell behavior.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
# Crawlora REST helper — minimal, dependency-free (curl only).
# Calls https://api.crawlora.net/api/v1 with your Crawlora API key.
# Get a free key (2,000 credits/mo, no card) at https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills.
#
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
# Crawlora REST helper — minimal, dependency-free (curl only).
# Calls https://api.crawlora.net/api/v1 with your Crawlora API key.
# Get a free key (2,000 credits/mo, no card) at https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills.
#
# Usage:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
# Crawlora REST helper — minimal, dependency-free (curl only).
# Calls https://api.crawlora.net/api/v1 with your Crawlora API key.
# Get a free key (2,000 credits/mo, no card) at https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills.
#
# Usage:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
# Crawlora REST helper — minimal, dependency-free (curl only).
# Calls https://api.crawlora.net/api/v1 with your Crawlora API key.
# Get a free key (2,000 credits/mo, no card) at https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills.
#
# Usage:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
# Crawlora REST helper — minimal, dependency-free (curl only).
# Calls https://api.crawlora.net/api/v1 with your Crawlora API key.
# Get a free key (2,000 credits/mo, no card) at https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills.
#
# Usage:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Keep the API key out of the curl process command line. A private temporary
# config supplies the header and is removed automatically on exit.
curl_config="$(mktemp "${TMPDIR:-/tmp}/crawlora-curl.XXXXXX")"
chmod 600 "$curl_config"
trap 'rm -f "$curl_config"' EXIT
printf 'header = "x-api-key: %s"\n' "$CRAWLORA_API_KEY" >"$curl_config"
auth=(--config "$curl_config")
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

External Transmission

Medium
Category
Data Exfiltration
Content
[ -n "$body" ] || body='{}'
  # Stream the body on stdin so curl never interprets a user value as its
  # @file shorthand (and cannot read local files supplied in a request body).
  printf '%s' "$body" | curl -fsS -X "$method" "${auth[@]}" \
    -H "Content-Type: application/json" --data-binary @- "${base}${path}"
fi
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Low
Confidence
88% confidence
Finding
This markdown file instructs users to call external endpoints via a script and states that requests require the `x-api-key: $CRAWLORA_API_KEY` header. While it is an endpoint reference, it does not include any explicit warning that using the skill will send request data to a third-party service and consume a credential from the environment.

Static analysis

No suspicious patterns detected.