Back to skill

Security audit

signalradar

Security checks for vulnerabilities and agentic risk

Overview

SignalRadar appears to do what it says: monitor Polymarket markets, store local monitoring state, and send alerts through disclosed user-configured channels.

Before installing, be aware that enabling scheduling creates a recurring background job, and configuring a webhook sends watched market questions and probabilities to that provider. Keep the default HTTPS/public-address/file-scope guards unless you deliberately need to override them, and use schedule disable or schedule clear-route to remove persistence.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (2)

T01 · Skill Instruction Hijacking

Error
Location
scripts/signalradar.py:1653
Finding

Persistent scheduled prompt forces verbatim branded agent output

Content
View full analysis
str: command = _scheduler_run_command("openclaw") # Scoped to this job's own output only. An earlier version told the agent # how to format its reply in absolute terms ("reply with exactly ... and # nothing else", "no markdown, no commentary"), which is output control # propagating from a scheduled job into the agent's session — the audit read # it as instruction hijacking. The need is narrow: the check's stdout is # already user-facing text, so it should be relayed rather than rewritten. return ( "Run this workspace's scheduled SignalRadar check.\n" f"Use Bash once with this command:\n{command}\n" "Its stdout is already the message for the user; relay it as-is rather " "than summarising or reformatting it. A stdout of HEARTBEAT_OK means " "there is nothing to report for this run." ) ``` The single-alert formatter adds a fixed promotional footer: ```python return ( "\U0001f4e1 SignalRadar Alert\n" "\n" f"{markers}{question}\n" f"\U0001f3af {baseline}% \u2192 {current}% ({direction + ' ' if direction else ''}{abs_pp}pp)\n" f"\U0001f504 Baseline updated to {current}%\n" f"{context_block}" "\n" f"\U0001f4c5 {ts_display}\n" "\n" "\u2014 Powered by SignalRadar" ) ``` The multi-alert formatter applies the same fixed footer: ```python header = "\U0001f4e1 SignalRadar Alert\n\n" footer = ( f"\n\n\U0001f4c5 {ts_display}\n" "\n" "\u2014 Powered by SignalRadar" ) ``` Digest output also includes the branding: ```python while lines and lines[-1] in ("", None): lines.p ...[truncated 2442 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/discover_entries.py:453
Finding

Unbounded HTTP response buffering permits memory-exhaustion denial of service

Content
View full analysis
list[Any]: """Fetch 7-day price history from the Polymarket CLOB API. NEVER raises. Returns the raw history point list, or [] on any failure (network error, timeout, HTTP error, bad JSON — and unknown tokens, for which CLOB returns HTTP 200 with {"history": []} rather than an error). Deliberately not routed through _api_get: different host, shorter timeout, and a never-raise contract (alerts must deliver even when CLOB is down). """ token = str(clob_token_id or "").strip() if not token: return [] try: url = ( f"{CLOB_API_BASE}/prices-history" f"?market={urllib.parse.quote(token)}&interval=1w&fidelity=360" ) assert_allowed_fetch_url(url) req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT}) with _allowlisted_opener().open(req, timeout=TREND_HTTP_TIMEOUT) as resp: data = json.loads(resp.read().decode("utf-8")) history = data.get("history") if isinstance(data, dict) else None return history if isinstance(history, list) else [] except Exception: return [] ``` The compatibility ingestion helper has the same issue: ```python def fetch_json(url: str, timeout: int) -> Any: assert_allowed_fetch_url(url) req = urllib.request.Request(url, headers={"User-Agent": "signalradar-skill/1.0"}) with _allowlisted_opener().open(req, timeout=timeout) as resp: return json.loads(resp.read().decode("utf-8")) ``` ### Technical Analysis Calling `resp.read()` without a b ...[truncated 2110 chars]
Remediation
View remediation
MAX_RESPONSE_BYTES: raise ValueError("Polymarket API response exceeded size cap") data = json.loads(body.decode("utf-8")) ``` 2. Centralize network reads in one shared helper so new API paths cannot accidentally omit the limit. 3. Validate `Content-Length` when present, while still enforcing a streaming byte limit because the header may be absent or false. 4. Consider a substantially smaller cap for price-history responses because this endpoint should return a limited number of data points. 5. Limit decompressed size when accepting compressed HTTP responses; a compressed response can otherwise bypass a wire-size-only limit. 6. Add tests using oversized responses for both `fetch_price_history_points()` and `fetch_json()`. 7. Ensure oversized-response failures degrade cleanly without preventing the core alert from being delivered when only optional trend enrichment fails. ]]>
Vulnerability Patterns
  • 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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (89)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This code does not implement the declared primary behavior of monitoring Polymarket markets or managing user monitors. Instead, it is an alert delivery adapter and routing layer. It takes already-produced events/reports, builds delivery envelopes, formats human-readable alert text, and sends/stores them through delivery channels. The code includes significant undeclared capabilities: outbound webhook delivery, local file writes, DNS resolution, redirect handling, and SSRF/path security controls. These may be supporting components within a larger SignalRadar system, but for this code chunk alone, the actual purpose is message delivery infrastructure rather than Polymarket monitoring/search/management. Therefore the declared description does not accurately represent what this supplied code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The core Polymarket-monitoring behavior matches the description well: the code supports adding markets, listing/removing monitors, showing current market info, discovering/searching markets, checking probabilities, and scheduling/running monitoring. However, the code also contains several substantive capabilities not reflected in the declared description or permissions: full configuration editing, installation/removal of persistent background schedulers, periodic digest reporting, and multi-channel outbound delivery infrastructure including webhook/file/openclaw plus storage of reply-route data. These are not mere implementation details because they create persistent machine state, background execution, and external message delivery capabilities. Therefore the description is incomplete enough to count as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code chunk does not implement the declared primary purpose of monitoring Polymarket prediction markets, checking probability changes, searching markets, managing monitors, or sending alerts. Instead, it validates the structure of JSON objects for internal SignalRadar protocol entities. While schema validation could be a supporting internal utility within a larger SignalRadar system, this specific code chunk’s actual behavior is materially different from the declared end-user functionality and exposes an undeclared file-based validation capability. Therefore this chunk is a description-behavior 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 14)May include surrounding context.

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
allowed-tools: "Bash(python3 scripts/signalradar.py:*)"

Static analysis

No suspicious patterns detected.