Back to skill

Security audit

Xpulse

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly does what it says, but it can still read Kalshi credentials and request private position data even when its documented position gate is disabled.

Review or patch the `position_gate` behavior before installing if you expect to run without Kalshi position matching. Treat the local cache, history, debug logs, and Kalshi key path as sensitive trading data, use pinned dependencies from `requirements.txt`, and avoid the optional bulk stack install unless you have reviewed those other skills too.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/xpulse.py:514
Finding

Position-gate configuration is ignored, causing unnecessary credential access and authenticated network requests

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
SKILL.md:33
Finding

Unpinned installation guidance and optional bulk Skill installation increase supply-chain exposure

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description promises a substantial social-signal scanning and filtering system for prediction market trading. However, the provided code chunk contains only an init.py file with a package docstring and no operational logic. Since the actual code does not implement or demonstrate any of the declared capabilities, the description does not accurately represent this supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description describes an end-user trading signal scanner with external content search, AI-based filtering, and position-aware alerting. The supplied code chunk is instead a low-level helper module for robustly parsing JSON-like responses from model output. It only manipulates input strings locally using json, regex, and brace matching. While such a utility could support a larger pipeline, this specific chunk does not implement the declared scanner behavior or any of its key capabilities. Therefore the description does not accurately represent what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

Manual reset:

bash
rm ~/.openclaw/state/x_signal_history.json

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documentation describes capabilities that require network access, local model invocation, filesystem writes, environment/config access, and scheduled execution, but it does not declare any explicit tool scope or permission boundaries. In an agent ecosystem, missing scope declarations weaken least-privilege controls and can cause the skill to receive broader access than users expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill processes sensitive trading topics and active Kalshi position data and sends derived content to external or local services such as DuckDuckGo, Kalshi, and Ollama, yet the description lacks a clear privacy warning or data-flow disclosure. Users may unknowingly expose trading interests, positions, and market thesis information to services or logs, which can create confidentiality and operational-risk issues.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The cache description states that all detected signals are written to .x_signal_cache.json, including suppressed signals, without warning that this creates a local retention store of potentially sensitive trading intelligence. If the host is shared, backed up, synced, or compromised, this cache could reveal market focus, inferred positions, and timing-sensitive information.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

Via crontab:

bash
# Add to crontab -e:
*/30 * * * * cd /path/to/xpulse && python -m xpulse.xpulse >> /tmp/xpulse.log 2>&1

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

Via launchd (macOS):

xml
<!-- ~/.launchd/com.xpulse.scanner.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

Via launchd (macOS):

xml
<!-- ~/.launchd/com.xpulse.scanner.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

Via launchd (macOS):

xml
<!-- ~/.launchd/com.xpulse.scanner.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

Via launchd (macOS):

xml
<!-- ~/.launchd/com.xpulse.scanner.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

xml
<!-- ~/.launchd/com.xpulse.scanner.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
**Expected behavior:** If you have no active Kalshi positions, all signals are suppressed (logged silently). This is intentional — position-aware alerting is the goal.

**To test:** Either:
1. Create a test Kalshi position matching your topic
2. Disable Stage 3: set `position_gate: false` in config (alerts all non-materiality signals)

### Signal History Growing Too Large

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The skill is designed to generate direct alerts and integrate with trade-oriented tooling, but it does not present a clear caution that automated or semi-automated signals can influence trading decisions and cause financial harm if incorrect, manipulated, or delayed. In a trading context, omission of that warning increases the risk of overreliance on noisy or adversarial social data.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation labels unmatched signals as 'silent' and the system as 'fail-closed', but it also states those signals are retained in state and cache for later consumption. That creates a confidentiality and expectation gap: users may believe unmatched portfolio-relevant signal data is discarded when it is actually persisted and accessible through other components.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This is a real issue because the 'suppressed' terminology suggests non-delivery and non-exposure, while the design actually exposes the data programmatically and via cache. In a trading context, suppressed signals may still reveal market interests, position alignment, or sensitive summaries to other local tools or users with access to state artifacts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file documents storage of signal topics, summaries, confidence, and matched position metadata in state/cache and debug logging without a clear user-facing disclosure of retention. In a prediction-market workflow, that local telemetry can reveal trading interests and potentially sensitive portfolio context, making it a legitimate privacy and data-handling weakness.

Content

No source excerpt is available for this finding.

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

Scanner excerpt · scripts/xpulse.py (reported line 103)May include surrounding context.

python
model = OLLAMA_CFG.get("model", "qwen3:latest")
    try:
        import urllib.request
        req = urllib.request.Request("http://localhost:11434/api/tags")
        with urllib.request.urlopen(req, timeout=5) as resp:
            data = json.loads(resp.read().decode("utf-8"))
            models = [m.get("name", "") for m in data.get("models", [])]

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

Scanner excerpt · scripts/xpulse.py (reported line 147)May include surrounding context.

python
"options": {"num_predict": 256},  # Cap output tokens — we only need short JSON
        }).encode("utf-8")

        req = urllib.request.Request(
            "http://localhost:11434/api/generate",
            data=payload,
            headers={"Content-Type": "application/json"},

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 · scripts/xpulse.py (reported line 164)May include surrounding context.

python
# Fallback: CLI with stdin pipe
    try:
        result = subprocess.run(
            ["ollama", "run", model],
            input=prompt,
            capture_output=True, timeout=timeout, text=True

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The skill reads Kalshi API credentials and a local private key even though its headline purpose is X/Twitter signal scanning. That expands the trust boundary significantly: compromise of this skill, prompt-driven misuse of downstream components, or log/debug leakage could expose trading credentials and enable unauthorized access to the user's portfolio context.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/position-matching.md (reported line 187)May include surrounding context.

md
private_key = f.read()

        config = Configuration(
            host="https://api.elections.kalshi.com/trade-api/v2"
        )
        config.api_key_id = api_key_id
        config.private_key_pem = private_key

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/xpulse.py (reported line 328)May include surrounding context.

python
private_key = f.read()

        config = Configuration(
            host="https://api.elections.kalshi.com/trade-api/v2"
        )
        config.api_key_id = api_key_id
        config.private_key_pem = private_key

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The inline comment claims 'Cache all Stage 1 signals for morning brief,' but the signals list at this point only contains topics whose analysis returned has_signal and met min_confidence. This contradicts the documented intent and could mislead maintainers about what downstream components receive.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.