Back to skill

Security audit

Prediction Stack Setup

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly purpose-aligned, but it handles trading and API credentials, persistent scheduled jobs, and includes unsafe troubleshooting steps that can expose secrets.

Install only if you are comfortable with ongoing market-scanning automation, iMessage delivery through BlueBubbles, and local storage of API credentials. Before running it, set ~/.openclaw to 0700 and ~/.openclaw/config.yaml plus private keys to 0600, avoid the troubleshooting steps that print keys or environment variables, review each cron job before adding it, and rotate any credential that has been displayed in a shared or logged terminal.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/validate_setup.py:92
Finding

Sensitive configuration file is created without restrictive permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/validate_setup.py:92-97
Vulnerability Type: Sensitive credential file created with permissions inherited from the process umask
Risk Level: Medium

Vulnerable Code

python
config_path = Path.home() / ".openclaw" / "config.yaml"

if not config_path.exists():
    # Generate template config on first run
    config_path.parent.mkdir(parents=True, exist_ok=True)
    config_path.write_text(_CONFIG_TEMPLATE)

Technical Analysis

The validator creates ~/.openclaw/config.yaml using Path.write_text() without explicitly assigning a restrictive file mode. The resulting permissions depend on the user's current umask. Under a permissive umask, the file may be readable by other local users.

Although the initially generated template only contains placeholders, the instructions direct the user to place Anthropic and Polygon API keys, along with the Kalshi API key identifier and private-key path, into this file. The script does not subsequently verify or correct its permissions.

This exceeds secure minimum-privilege handling for a credential-bearing configuration file because access is not explicitly limited to the owning user.

Attack Path

  1. A user runs validate_setup.py when ~/.openclaw/config.yaml does not exist.
  2. The script creates the configuration file with permissions derived from the current umask.
  3. The user follows the setup instructions and inserts valid API credentials into the generated file.
  4. Another local account or process with filesystem access reads the configuration file.
  5. The exposed credentials are reused to make unauthorized API requests or incur usage charges.

Exploitation requires local filesystem access or another process executing under an identity permitted to read the file.

Impact Assessment

An attacker may obtain:

  • The Anthropic API key, enabling unauthorized billable API requests.
  • The Polygon API key, enabling unauthorized use of the associ ...[truncated 359 chars]
Remediation
View remediation

Remediation Suggestions

  1. Create the OpenClaw configuration directory with owner-only permissions:
python
config_path.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
os.chmod(config_path.parent, 0o700)
  1. Create the file atomically with mode 0600 rather than relying on the process umask:
python
fd = os.open(
    config_path,
    os.O_WRONLY | os.O_CREAT | os.O_EXCL,
    0o600,
)
with os.fdopen(fd, "w", encoding="utf-8") as config_file:
    config_file.write(_CONFIG_TEMPLATE)
  1. Check existing file permissions before loading credentials and warn or fail when group or world access is present:
python
mode = config_path.stat().st_mode & 0o777
if mode & 0o077:
    raise PermissionError(
        f"{config_path} has insecure permissions {oct(mode)}; use chmod 600"
    )
  1. Prefer environment variables, an operating-system credential store, or a dedicated secrets manager for API secrets.

  2. Document that ~/.openclaw/config.yaml must use mode 0600 and ~/.openclaw should use mode 0700.

T09 · Insecure Skill Coding Practices

Warning
Location
references/validation-troubleshooting.md:48
Finding

Troubleshooting instructions disclose API and private-key material in terminal output

Content
View full analysis

Vulnerability Details

File Location: references/validation-troubleshooting.md:48-87
Vulnerability Type: Sensitive information exposure through terminal output
Risk Level: Medium

Vulnerable Instructions

markdown
#### Error: "File not found: Check private_key_file path in config"

**Diagnosis:** The path to your private key doesn't exist.

**Fix steps:**
1. Check file exists: `ls -la ~/.openclaw/keys/kalshi-secret.pem`
2. If not found, download it from https://kalshi.com/settings/api again
3. Paste into file:
   ```bash
   nano ~/.openclaw/keys/kalshi-secret.pem
   # Paste your private key (should start with -----BEGIN PRIVATE KEY-----)
   # Press Ctrl+O, Enter, Ctrl+X to save
  1. Verify: cat ~/.openclaw/keys/kalshi-secret.pem | head -5
  2. Check permissions: chmod 600 ~/.openclaw/keys/kalshi-secret.pem
  3. Rerun: python validate_setup.py --kalshi-only

Anthropic (Claude) API Validation Fails

Error: "Invalid or expired API key"

Diagnosis: Your API key is invalid, expired, or incorrectly formatted.

Fix steps:

  1. Go to https://console.anthropic.com/account/keys
  2. Check if you have any active keys (not revoked or expired)
  3. If not, click "Create New Key"
  4. Copy the full key (looks like sk-ant-...)
  5. Update ~/.openclaw/config.yaml:
    yaml
    anthropic:
      api_key: "sk-ant-YOUR_NEW_KEY_HERE"
    
    OR set as environment variable:
    bash
    export ANTHROPIC_API_KEY="sk-ant-YOUR_NEW_KEY_HERE"
    
  6. Verify: echo $ANTHROPIC_API_KEY (should show your key, not empty)
  7. Rerun: python validate_setup.py --verbose
text

### Technical Analysis

The troubleshooting guide recommends printing sensitive credential material directly to the terminal:

- `cat ~/.openclaw/keys/kalshi-secret.pem | head -5` displays part of the private key.
- `echo $ANTHROPIC_API_KEY` displays the complete Anthropic API key.

Terminal output may be retained in scrollback, captured by session-recording or monitoring s
...[truncated 1894 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace private-key content display with existence, ownership, permission, and non-empty checks:
bash
test -s ~/.openclaw/keys/kalshi-secret.pem \
  && echo "Private key file exists and is non-empty" \
  || echo "Private key file is missing or empty"

stat -f "%Sp %Su" ~/.openclaw/keys/kalshi-secret.pem 2>/dev/null \
  || stat -c "%A %U" ~/.openclaw/keys/kalshi-secret.pem
  1. Validate the private-key format without printing its contents, for example by parsing it with a trusted cryptographic tool and displaying only a public-key fingerprint.

  2. Replace echo $ANTHROPIC_API_KEY with a non-disclosing presence check:

bash
if [ -n "${ANTHROPIC_API_KEY:-}" ]; then
  echo "ANTHROPIC_API_KEY is configured"
else
  echo "ANTHROPIC_API_KEY is not configured"
fi
  1. If format diagnostics are necessary, show only a short, explicitly masked prefix and the total length. Never display the complete value.

  2. Add guidance warning users not to paste credential values, private-key contents, verbose authentication errors, or unredacted configuration files into support tickets, chat sessions, screenshots, or logs.

  3. Recommend immediate revocation and rotation if a credential has been displayed in a recorded or shared terminal session.

Vulnerability Patterns
  • 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
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (27)

Tainted flow: 'api_key' from os.getenv (line 270, credential/environment) → requests.get (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/validate_setup.py (reported line 281)May include surrounding context.

python
import requests

        # Test with a simple ticker query
        response = requests.get(
            "https://api.polygon.io/v1/marketstatus",
            params={"apikey": api_key},
            timeout=5

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description portrays a broad interactive installer/reconfiguration wizard with orchestration features, scheduling, messaging tests, and system integration. The supplied code instead performs API/config validation only. It creates a default config template if missing, reads configuration from ~/.openclaw/config.yaml, and makes network calls to validate Kalshi, Anthropic, Polygon, Ollama, and Polymarket availability. There is no evidence of interactivity beyond CLI flags, no cron setup, no heartbeat management, no iMessage testing, and no skill discovery or stack wiring. This is a material mismatch in primary purpose and capabilities.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README advertises that the skill will create scheduled jobs, route alerts through iMessage/BlueBubbles, and collect API keys, but it does not clearly warn users that it will modify local system scheduling, handle sensitive credentials, and send data to external messaging infrastructure. In a setup wizard context, users may proceed with elevated trust and grant access without understanding persistence, data exposure, or where secrets are stored, increasing the chance of unintended system changes or credential leakage.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill instructs use of capabilities that touch local files, credentials, environment configuration, and external network services, but it does not declare any tool scope or permission boundaries. In a setup skill that edits config, stores secrets, validates APIs, and schedules recurring jobs, the absence of explicit allowed-tools makes the blast radius unclear and increases the chance of over-privileged execution or unintended access to sensitive data.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The skill instructs users to persist long-lived credentials in ~/.openclaw/config.yaml and a private key file, creating durable local access to external trading and messaging-related services. Persistent secrets are a common target because they survive sessions, may be copied into backups or synced storage, and can be reused by other local processes or future jobs created by the stack.

Content

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

Phase 2: API Key Configuration

Create or update ~/.openclaw/config.yaml:

yaml
# === REQUIRED ===

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill directs users to place API credentials and private-key material into persistent local configuration and files without an explicit warning about secret handling risks, backup exposure, shell history leakage, multi-user systems, or repository sync. Because this setup also validates credentials against live services and wires recurring jobs, compromise of these stored secrets could enable account access, message abuse, or ongoing unauthorized automation.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · config.example.yaml (reported line 15)May include surrounding context.

yaml
kalshi:
  enabled: true
  api_key_id: "YOUR_KALSHI_KEY_ID"                    # Settings → API Keys on kalshi.com
  private_key_file: "~/.openclaw/keys/kalshi-secret.pem"  # chmod 600 this file

anthropic:
  api_key: "YOUR_ANTHROPIC_API_KEY"                  # Required for the reference Kalshalyst path

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

  1. If not, generate a new one
  2. Download the private key file
  3. Save it to ~/.openclaw/keys/kalshi-secret.pem
  4. Verify permissions: chmod 600 ~/.openclaw/keys/kalshi-secret.pem
  5. Update ~/.openclaw/config.yaml:
    yaml
    kalshi:
    

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/validation-troubleshooting.md (reported line 19)May include surrounding context.

  1. If not, generate a new one
  2. Download the private key file
  3. Save it to ~/.openclaw/keys/kalshi-secret.pem
  4. Verify permissions: chmod 600 ~/.openclaw/keys/kalshi-secret.pem
  5. Update ~/.openclaw/config.yaml:
    yaml
    kalshi:
    

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · references/validation-troubleshooting.md (reported line 62)May include surrounding context.

  1. If not, generate a new one
  2. Download the private key file
  3. Save it to ~/.openclaw/keys/kalshi-secret.pem
  4. Verify permissions: chmod 600 ~/.openclaw/keys/kalshi-secret.pem
  5. Update ~/.openclaw/config.yaml:
    yaml
    kalshi:
    

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The guide instructs users to paste a private key into a local file and then verify it with cat ... | head -5, which unnecessarily displays sensitive key material in plaintext. Even partial private key exposure can leak into terminal logs, recordings, clipboard history, remote support sessions, or shell auditing systems, making this especially risky in an interactive setup workflow.

Content

No source excerpt is available for this finding.

File System Enumeration

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.

Content

Scanner excerpt · references/validation-troubleshooting.md (reported line 53)May include surrounding context.

Diagnosis: The path to your private key doesn't exist.

Fix steps:

  1. Check file exists: ls -la ~/.openclaw/keys/kalshi-secret.pem
  2. If not found, download it from https://kalshi.com/settings/api again
  3. Paste into file:
    bash

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The troubleshooting guide tells users to place a live Anthropic API key directly into config files or export it into the shell, but it does not warn about secret handling risks such as shell history exposure, screen sharing, terminal logging, or committing config files to source control. In a setup skill focused on automation and scheduling, this increases the chance that long-lived credentials are stored insecurely and later exfiltrated.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The guide encourages creating and copying a long-lived API key into configuration or environment variables without warning about persistence risks. In a stack that also creates cron jobs and automation, persistent secrets may be inherited by processes, stored in dotfiles, backed up, or exposed through shell history and operational tooling.

Content

Scanner excerpt · references/validation-troubleshooting.md (reported line 76)May include surrounding context.

Fix steps:

  1. Go to https://console.anthropic.com/account/keys
  2. Check if you have any active keys (not revoked or expired)
  3. If not, click "Create New Key"
  4. Copy the full key (looks like sk-ant-...)
  5. Update ~/.openclaw/config.yaml:
    yaml

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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/validation-troubleshooting.md (reported line 219)May include surrounding context.

Check network connectivity:

bash
# Kalshi
curl -I https://api.kalshi.com/

# Anthropic
curl -I https://api.anthropic.com/

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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/validation-troubleshooting.md (reported line 222)May include surrounding context.

md
curl -I https://api.kalshi.com/

# Anthropic
curl -I https://api.anthropic.com/

# Polygon.io
curl -I https://api.polygon.io/

Known Vulnerable Dependency: requests==2.32.5 — 2 advisory(ies): CVE-2026-25645 (Requests has Insecure Temp File Reuse in its extract_zipped_paths() utility func); CVE-2026-25645 (Requests is a HTTP library. Prior to version 2.33.0, the `requests.utils.extract)

Medium
Category
Supply Chain
Confidence
98% confidence
Finding

The dependency is pinned to requests==2.32.5, and the finding indicates this version is affected by a known vulnerability fixed in 2.33.0 involving insecure temporary file reuse in extract_zipped_paths(). Even if that utility is not obviously used from this requirements file alone, shipping a known-vulnerable pinned version in an automation-focused stack increases exposure because downstream code or transitive usage may invoke the affected functionality.

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

python
except ImportError:
            from kalshi_python import Configuration, KalshiClient

        config_obj = Configuration(host="https://api.elections.kalshi.com/trade-api/v2")
        with open(key_path, 'r') as f:
            config_obj.private_key_pem = f.read()
        config_obj.api_key_id = key_id

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script performs real outbound validation calls using configured credentials and prompts without an explicit up-front warning or consent step, which can surprise users and cause unintended credential use, billing, or metadata disclosure. In a setup skill that may be run interactively, hidden network/probing behavior is more sensitive because users may expect passive validation rather than active API invocation.

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/validation-troubleshooting.md (reported line 225)May include surrounding context.

md
# Test with a simple ticker query
        response = requests.get(
            "https://api.polygon.io/v1/marketstatus",
            params={"apikey": api_key},
            timeout=5
        )

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/validate_setup.py (reported line 282)May include surrounding context.

python
# Test with a simple ticker query
        response = requests.get(
            "https://api.polygon.io/v1/marketstatus",
            params={"apikey": api_key},
            timeout=5
        )

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/validate_setup.py (reported line 330)May include surrounding context.

python
import requests

        # Test 1: Check if Ollama server is running
        response = requests.get(
            "http://localhost:11434/api/tags",
            timeout=3
        )

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/validate_setup.py (reported line 352)May include surrounding context.

python
return result

        # Test 3: Try a simple inference
        response = requests.post(
            "http://localhost:11434/api/generate",
            json={
                "model": model_name,

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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/validate_setup.py (reported line 352)May include surrounding context.

python
return result

        # Test 3: Try a simple inference
        response = requests.post(
            "http://localhost:11434/api/generate",
            json={
                "model": model_name,

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/validate_setup.py (reported line 352)May include surrounding context.

python
return result

        # Test 3: Try a simple inference
        response = requests.post(
            "http://localhost:11434/api/generate",
            json={
                "model": model_name,

Static analysis

No suspicious patterns detected.