Back to skill

Security audit

Wm Tipp

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed German World Cup tip sender that fetches public odds and posts to configured Telegram recipients, with no evidence of hidden or destructive behavior.

Install only if you are comfortable with the skill sending generated World Cup tip messages to the Telegram recipients you configure. Set WM_TELEGRAM_API to a trusted Telegram gateway, keep WM_CHAT_IDS limited to intended recipients, and do not set WM_SKILL_DIR to a sensitive directory.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • 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
Findings (8)

Tainted flow: 'req' from os.environ.get (line 78, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/wm_tipps.py (reported line 82)May include surrounding context.

python
"Content-Type": "application/json",
            "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36"
        })
        with urllib.request.urlopen(req, timeout=15) as resp:
            data = json.loads(resp.read().decode())

        # Filtere nur WM-relevante, offene Märkte

Tainted flow: 'req' from os.environ.get (line 78, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

send_telegram posts the full generated message and recipient chat ID to TELEGRAM_API, which is taken from the WM_TELEGRAM_API environment variable with no allowlisting or validation. If an attacker can alter that variable, they can redirect outbound requests to an arbitrary internal or external endpoint, enabling SSRF and exfiltration of message contents and recipient metadata.

Content

Scanner excerpt · scripts/wm_tipps.py (reported line 346)May include surrounding context.

python
req = urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"})
    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            return resp.status == 200
    except Exception as e:
        print(f"Telegram error: {e}", file=sys.stderr)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares environment variables and describes networked behavior and file writes, but it does not declare an explicit tool scope such as permissions or allowed-tools. This creates an authorization gap: operators may install or trust the skill without a clear machine-readable statement of its runtime capabilities, increasing the chance of over-privileged execution or unnoticed data exfiltration through Telegram/network access.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This Python file contains natural-language descriptions and user-facing output that are explicitly German-only, including the module docstring and later Telegram message text. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is clearly documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Tainted flow: 'CACHE_FILE' from os.environ.get (line 18, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
86% confidence
Finding

CACHE_FILE is derived from WM_SKILL_DIR, which is environment-controlled, and is opened for writing without validation. If an attacker can influence that environment variable, they can redirect writes to arbitrary filesystem locations accessible to the process, causing file overwrite, data corruption, or planting files in unintended paths.

Content

Scanner excerpt · scripts/wm_tipps.py (reported line 55)May include surrounding context.

python
return {"fetched_at": None, "markets": {}}

def save_cache(cache):
    with open(CACHE_FILE, "w") as f:
        json.dump(cache, f, indent=2)

def is_cache_valid(cache):

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest describes 'WM 2026 Tipps mit Polymarket-Quoten' and automatic daily tips to Telegram, which implies the betting tips are based on Polymarket odds. In the implementation, the actual predictions come from the static TIPS dictionary and get_tipp(), while Polymarket data is only appended as contextual information in the message.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The JSON content uses German-only natural-language values such as 'bis', 'Gruppen', 'Gruppenphase', and country/city names localized to German, with no indication that this locale is optional or region-specific. Under the policy rule, forcing a specific language or locale without user choice can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The inline comment '# An alle Tipper senden' suggests messages are sent to all tipsters/authors, but the loop actually iterates over TIPPERS loaded from WM_CHAT_IDS and sends to their chat_id values. This is a mild intent/documentation mismatch because the runtime behavior is recipient-driven broadcasting, not sending to some internally defined set of 'tippers.'

Content

No source excerpt is available for this finding.