Back to skill

Security audit

SeeSaw Claw

Security checks for vulnerabilities and agentic risk

Overview

This is a real SeeSaw prediction-market client, but it needs Review because it can run live financial and account-changing automation with weak safeguards.

Install only if you understand that this skill can affect real SeeSaw account state and funds. Before using automation, set dry_run to true, avoid --yes for live workflows, verify SEESAW_BASE_URL is the intended HTTPS SeeSaw endpoint, protect and rotate API keys, and avoid running LLM/search-driven trading or oracle scripts until they require explicit per-transaction review and safer token storage.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
skills/seesaw/scripts/seesaw.py:13
Finding

SeeSaw credentials can be transmitted to an untrusted or plaintext endpoint

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
skills/seesaw/scripts/seesaw.py:9
Finding

Bearer token is stored in a predictable shared temporary file

Content
View full analysis
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
skills/seesaw/scripts/open_position.py:113
Finding

Untrusted search content can influence automated financial transactions through the LLM

Content
View full analysis
0.7: option_name = analysis.get('option_to_buy') option_id = find_option_id(options, option_name) if option_id: amount = config.get("max_position_size", 100) print(f"Executing BUY for {title} - Option: {option_name} (ID: {option_id})") if not dry_run: try: resp = client.buy(market_id, option_id, amount) ``` ```python # skills/seesaw/scripts/adjust_position.py search_query = f"{title} news update" search_result_data = search_web(search_query, topic="news", days=1) news_text = search_result_data["text"] prompt = f""" Analyze my position in prediction market: "{title}" Current Position: Holding {current_shares} shares o ...[truncated 3043 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
skills/seesaw/scripts/auto_assert.py:20
Finding

Hard-coded creator identity redirects “my markets” automation to a fixed third-party account

Content
View full analysis
{option_name}\n理由: {resolution['reasoning']}") except Exception as e: slack_updates.append(f"❌ *断言失败*: {title} -> {option_name} ({e})") else: comment = generate_progress_comment(market, news_text) if comment: if not dry_run: try: client.add_comment(market_id, comment) ``` ```python # skills/seesaw/scripts/my_markets.py MY_ID = "fca3cb34-04f0-4af6-b0cc-9c05281f341b" my_markets = [m for m in all_m if m.get("creator", {}).get("id") == MY_ID] ``` ### Technical Analysis The workflow describes the selected records as the current user's markets, but it never derives th ...[truncated 1686 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
skills/seesaw/scripts/utils.py:129
Finding

Gemini API key is embedded in the request URL

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
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (39)

Tainted flow: 'url' from os.getenv (line 147, 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 · skills/seesaw/scripts/utils.py (reported line 58)May include surrounding context.

python
url = "https://api.search.brave.com/res/v1/images/search"
        params = {"q": query, "count": max_results}
        try:
            resp = requests.get(url, headers=headers, params=params, timeout=10)
            data = resp.json()
            images = [item.get("properties", {}).get("url") for item in data.get("results", [])]
            return {"text": "", "images": [img for img in images if img]}

Tainted flow: 'url' from os.getenv (line 147, 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 · skills/seesaw/scripts/utils.py (reported line 69)May include surrounding context.

python
url = "https://api.search.brave.com/res/v1/images/search"
        params = {"q": query, "count": max_results}
        try:
            resp = requests.get(url, headers=headers, params=params, timeout=10)
            data = resp.json()
            images = [item.get("properties", {}).get("url") for item in data.get("results", [])]
            return {"text": "", "images": [img for img in images if img]}

Tainted flow: 'url' from os.getenv (line 147, credential/environment) → requests.post (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 · skills/seesaw/scripts/utils.py (reported line 113)May include surrounding context.

python
}
    
    try:
        resp = requests.post(url, json=payload, headers=headers, timeout=15)
        resp.raise_for_status()
        data = resp.json()
        if not data.get("ok"):

Tainted flow: 'url' from os.getenv (line 147, credential/environment) → requests.post (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 · skills/seesaw/scripts/utils.py (reported line 160)May include surrounding context.

python
}

    try:
        resp = requests.post(url, json=payload, headers=headers, timeout=60)
        resp.raise_for_status()
        data = resp.json()
        return data["candidates"][0]["content"]["parts"][0]["text"]

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code can settle completed markets and execute live trades through the Seesaw client even though no manifest scope or permission boundary is shown. In an agent skill context, undisclosed live financial side effects are dangerous because the skill can modify real positions and move funds if invoked with valid credentials.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Settlement and trading operations are performed automatically once conditions are met, with no user confirmation step before modifying positions. For a financial automation skill, this lack of approval significantly increases the chance of unintended loss from bad data, model errors, misconfiguration, or malicious prompting through external inputs.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The client defaults to http://localhost:3000/v1 and transmits api_key and api_secret during login, which means credentials may be sent in cleartext if the service is not strictly local or if traffic is intercepted/redirected. Even on local systems, insecure defaults normalize unsafe deployment and can expose secrets through proxies, port-forwarding, or compromised hosts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill documentation instructs users to store API credentials in a local config file and also shows passing secrets directly on the command line. Command-line arguments can be exposed via shell history, process listings, logs, or terminal recording, and the markdown provides no warning or safer alternative handling guidance.

Content

No source excerpt is available for this finding.

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 86)May include surrounding context.

text

```bash
mkdir -p ~/.openclaw/workspace/skills
cp -R skills/seesaw ~/.openclaw/workspace/skills/

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 · skills/seesaw/SKILL.md (reported line 69)May include surrounding context.

bash
git clone https://github.com/SeesawTech/SeeSaw-Claw.git
mkdir -p ~/.openclaw/workspace/skills
cp -R SeeSaw-Claw/skills/seesaw ~/.openclaw/workspace/skills/
pip install -r ~/.openclaw/workspace/skills/seesaw/requirements.txt
openclaw skills check

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation instructs users to configure API credentials and perform live financial trading actions, but it does not prominently warn about secret handling, real-money exposure, or the risk of unintended trades. In an agent skill context, this increases the chance that users paste sensitive keys into unsafe places or run commands assuming they are harmless, leading to account compromise or monetary loss.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill documents account-affecting and potentially irreversible operations such as buy, sell, claim, follow/block, comment deletion, oracle actions, and market creation without clear warnings about permanence or user confirmation requirements. In a prediction-market environment, misuse of these commands can cause financial loss, reputation impact, or irreversible market/account state changes.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script pulls untrusted external news content and feeds it to an LLM, then directly uses the model's JSON output to decide whether to buy, sell, or hold a live prediction-market position. This creates an unsafe autonomous decision loop where prompt-influenced or low-quality inputs can trigger financial actions without deterministic controls, making the trading behavior easy to manipulate or degrade.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The prompt explicitly instructs the model to 'Write a short update (in Chinese...)', which imposes a fixed language policy on output. There is no visible opt-in, configuration, or documentation here indicating that Chinese-only output is required or user-selected.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The script sends derived market subjects to a web search service and then forwards up to 1500–2000 characters of retrieved news text into LLM prompts. While the script logs high-level progress, it does not disclose in comments, docstrings, or user-facing warnings that market-related content will be sent to external services.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script performs a state-changing reward claim by calling client.claim_challenge(c_id) as part of normal execution, with only console logging and an optional dry-run as safeguards. This can cause unintended claims if the script is run in the wrong environment, by automation, or by a user who does not realize it will irreversibly act on available rewards.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script transmits the proposed title, description, probabilities, and image URL to Slack before the interactive confirmation step. Although the action is logged by surrounding print statements, the file does not disclose to the user that generated content will be sent to an external messaging service prior to approval, which is a network/data-sharing operation.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
96% confidence
Finding

In dry-run mode, the script automatically sets confirmation to yes, bypassing the human approval gate for the decision path. Although dry-run does not create the market in this file, it still simulates approval and can normalize unattended operation of an LLM-driven workflow that selects and advances external content without meaningful review, increasing the chance of unsafe or misleading outputs being treated as approved.

Content

Scanner excerpt · skills/seesaw/scripts/generate_topic.py (reported line 176)May include surrounding context.

python
confirm = "y"
    elif dry_run:
        confirm = "y"
        print("[DRY-RUN] Auto-confirming.")
    else:
        confirm = input("Create this market? (y/n): ")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script places real buy orders directly from LLM-generated recommendations once a confidence threshold is met, with no human approval, secondary validation, or hard safety guard. Because the decision input includes untrusted external news/search content and a non-deterministic model response, prompt manipulation, bad model judgment, or malformed output could trigger unintended live trades and financial loss.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The authentication token is cached in /tmp/seesaw_token.json, a shared world-accessible temporary location on many systems, with no file permission hardening or expiration handling. Other local users or processes could read or replace the token, leading to account/session hijacking or unauthorized API actions.

Content

No source excerpt is available for this finding.

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

python
url = f"{self.base_url}/auth/agent-login"
        payload = {"api_key": self.api_key, "api_secret": self.api_secret}
        try:
            resp = requests.post(url, json=payload, timeout=10)
            if not resp.ok: print(f"Error Body: {resp.text}")
            resp.raise_for_status()
        except requests.exceptions.RequestException as e:

Cloud Storage Exfiltration

Medium
Category
Data Exfiltration
Confidence
55% confidence
Finding

Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.

Content

Scanner excerpt · skills/seesaw/scripts/seesaw.py (reported line 600)May include surrounding context.

python
print(json.dumps(client.create_market(args.title, args.options, args.probs, args.end_time, args.description, args.images), indent=2))
        elif args.command == "upload":
            presigned = client.get_presigned_url(args.type, args.ext)
            client.upload_file(presigned["upload_url"], args.file, args.type)
            print(json.dumps({"file_url": presigned["file_url"]}, indent=2))
        elif args.command == "create-share-link":
            print(json.dumps(client.create_share_link(args.market_id, args.image_url, args.share_source, args.share_target), indent=2))

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · skills/seesaw/scripts/utils.py (reported line 43)May include surrounding context.

python
"""Parse command line arguments including standard ones like --dry-run."""
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument("--dry-run", action="store_true", help="Simulate actions without executing")
    parser.add_argument("--yes", action="store_true", help="Skip confirmation prompts")
    return parser.parse_args()

def search_web(query, topic=None, days=3, max_results=5, include_images=False):

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The code issues outbound requests to Brave search endpoints for web and image retrieval. Because no manifest or declared purpose is provided, this network-search capability is unjustified by the available intent context and represents a broader capability than a neutral local utility helper would imply.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

Image search sends the query to Brave Search, an external provider. If the query contains sensitive user or workspace data, that information leaves the environment without any visible consent mechanism in this helper.

Content

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

python
headers = {"Accept": "application/json", "X-Subscription-Token": brave_key}
    if include_images:
        url = "https://api.search.brave.com/res/v1/images/search"
        params = {"q": query, "count": max_results}
        try:
            resp = requests.get(url, headers=headers, params=params, timeout=10)

Static analysis

No suspicious patterns detected.