Back to skill

Security audit

Trading Card Game

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent game-integration skill, but its examples and docs expose API keys and webhook-driven gameplay in ways users should review before installing or running.

Install only if you are comfortable giving the skill an LTCG API key and allowing it to make game and matchmaking actions. Use a dedicated, revocable game API key; avoid running the webhook examples on the public internet until signature verification fails closed, request sizes are limited, and events are validated. Do not point LTCG_API_URL at untrusted hosts, do not run registration in shared logs or CI, and treat webhook.site as test-only because it receives gameplay metadata.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (6)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
examples/advanced-agent.ts:522
Finding
Unauthenticated Webhook Can Trigger Authenticated Gameplay Actions<![CDATA[ ## Vulnerability Details **File Location**: `examples/advanced-agent.ts:522-532` **Vulnerability Type**: Missing webhook authentication and input validation **Risk Level**: High ### Vulnerable Code ```typescript if (req.method === "POST" && req.url === "/webhook") { let body = ""; req.on("data", (chunk) => { body += chunk.toString(); }); req.on("end", async () => { try { const event: WebhookEvent = JSON.parse(body); await this.handleWebhook(event); ``` The accepted event is subsequently passed to an action-capable handler: ```typescript case "turn_start": if (event.gameId === this.currentGameId) { this.log(`Turn ${event.turnNumber} started (phase: ${event.phase})`); await this.playTurn(event.gameId); } break; ``` ### Technical Analysis The public webhook accepts JSON without verifying an HMAC signature, access token, trusted source, timestamp, nonce, event schema, or game ownership. The TypeScript type annotation does not provide runtime validation. The request body also has no size limit. An attacker who can reach the listener can submit arbitrarily large bodies or forged game events. A valid-looking `turn_start` event for the current game reaches `playTurn()`, which uses the agent's bearer credential to perform game actions. Although receiving webhooks is necessary for the Skill's declared real-time gameplay functionality, accepting unauthenticated action-triggering messages exceeds the minimum privileges required. ### Attack Path 1. The user exposes port 3000 through a public tunnel or cloud deployment, as directed by the example documentation. 2. An attacker identifies the `/webhook` endpoint. 3. The attacker submits a forged `game_start` event to set `currentGameId`, or obtains a game ID from logs or other exposed metadata. 4. The attacker submits a forged `turn_start` event for that game. 5. `handleWebhook()` accepts the event and invokes `playTurn()`. 6. The agent performs authenticated summo ...[truncated 484 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Require a webhook signing secret and fail startup if it is absent. - Verify an HMAC over the exact raw request bytes before parsing JSON. - Use `crypto.timingSafeEqual()` with equal-length buffers. - Reject missing, malformed, stale, or duplicate signatures. - Validate every event with a runtime schema and allowlist known event names. - Confirm that `gameId` belongs to an active game associated with the authenticated agent. - Add a strict request-body limit and endpoint rate limiting. - Return the response promptly and process authenticated events through a bounded queue. - Bind to localhost by default and require explicit configuration before exposing the service publicly. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scenarios/tournament-bot.md:36
Finding
Tournament Webhook Authentication Fails Open When the Secret Is Missing<![CDATA[ ## Vulnerability Details **File Location**: `scenarios/tournament-bot.md:36-52` **Vulnerability Type**: Fail-open authentication configuration **Risk Level**: High ### Vulnerable Code ```javascript const LTCG_API_KEY = process.env.LTCG_API_KEY; const WEBHOOK_SECRET = process.env.LTCG_WEBHOOK_SECRET; // Game state in-memory cache const gameStates = new Map(); const gameQueues = new Map(); // Queue for sequential processing function verifySignature(payload, signature) { if (!WEBHOOK_SECRET) return true; // Skip if no secret set const hash = crypto .createHmac('sha256', WEBHOOK_SECRET) .update(JSON.stringify(payload)) .digest('hex'); return signature === hash; } app.post('/webhook', async (req, res) => { ``` ### Technical Analysis The example treats the absence of `LTCG_WEBHOOK_SECRET` as successful authentication. Configuration errors therefore silently convert a protected action endpoint into a public endpoint. The signature comparison also uses ordinary string equality rather than a constant-time comparison. In addition, signing `JSON.stringify(req.body)` can fail to reproduce the exact bytes signed by the sender if serialization or middleware changes formatting. ### Attack Path 1. An operator deploys the tournament example without setting `LTCG_WEBHOOK_SECRET`. 2. `verifySignature()` returns `true` for every request. 3. An attacker sends arbitrary events to `/webhook`. 4. The endpoint queues the attacker-controlled event by `gameId`. 5. The event is passed to `handleWebhook()` and can influence action-capable tournament processing. 6. Repeated events can manipulate bot behavior or consume queue, memory, and API resources. ### Impact Assessment The flaw allows unauthenticated callers to cross the webhook trust boundary and influence tournament automation. The effective scope includes the bot's game actions and application resources, but no evidence shows direct host-level privilege escalation. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Abort application startup when `LTCG_WEBHOOK_SECRET` is missing or uses a placeholder. - Reject every webhook with a missing or malformed signature. - Verify the signature over the raw request body rather than reserialized JSON. - Compare fixed-length digest buffers using `crypto.timingSafeEqual()`. - Validate timestamps and nonces to prevent replay. - Add runtime event validation, rate limiting, body-size limits, and bounded queues. - Document secret generation, rotation, storage, and revocation requirements. ]]>

other

Warning
Location
scenarios/webhook-setup.md:43
Finding
Live Game Metadata Is Directed to a Third-Party Webhook Capture Service<![CDATA[ ## Vulnerability Details **File Location**: `scenarios/webhook-setup.md:43-82` **Vulnerability Type**: Third-party disclosure of gameplay and account metadata **Risk Level**: Medium ### Vulnerable Code ```markdown ## Quick Start: Using webhook.site The easiest way to test webhooks is webhook.site. It gives you a unique URL that captures all requests. 1. Visit https://webhook.site 2. You'll get a unique URL like `https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` 3. Use this URL when registering your webhook below ``` ```bash curl -X POST https://lunchtable.cards/api/game/webhooks \ -H "Authorization: Bearer $LTCG_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "events": ["turn_start", "turn_end", "game_end"], "url": "https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "secret": "my_optional_signing_secret" }' ``` Documented events include fields such as: ```json { "gameId": "game_xyz789", "lobbyId": "lobby_abc123", "playerId": "user_123", "playerUsername": "MyFirstBot", "opponentUsername": "AgentSmith42", "yourLifePoints": 7200, "opponentLifePoints": 6500 } ``` ### Technical Analysis The guide instructs users to register a third-party request-capture service as the recipient of live LTCG events. The bearer API key remains confined to the registration request sent to `lunchtable.cards`; it is not directly sent to `webhook.site`. However, subsequent webhook payloads disclose player identifiers, usernames, lobby and game identifiers, match state, and results to that third party. Using an external capture service can be reasonable for synthetic testing, but the guide does not prominently warn users about third-party retention, public-link exposure, or the need to avoid production accounts and sensitive match data. ### Attack Path 1. A user follows the quick-start instructions and obtains a webhook.site URL. 2. The user registers that URL for live turn and game events. 3. LTCG sends event ...[truncated 470 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Recommend a user-controlled endpoint as the default. - Restrict webhook.site usage to synthetic test accounts and non-sensitive test events. - Add a prominent warning explaining that payloads are transmitted to and retained by a third party. - Tell users to protect and delete the unique capture URL after testing. - Avoid placing production player identifiers or match data in third-party testing systems. - Document the provider's retention policy and provide a local test receiver alternative. - Use separate, short-lived webhook secrets for testing. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
examples/basic-agent.ts:26
Finding
Environment-Controlled API Base URL Can Receive the Bearer Credential<![CDATA[ ## Vulnerability Details **File Locations**: - `examples/basic-agent.ts:26, 115-125` - `examples/advanced-agent.ts:29, 110-118` - `examples/basic-agent.py:44, 107-121` **Vulnerability Type**: Unrestricted credential destination **Risk Level**: High ### Vulnerable Code TypeScript configuration and request sink: ```typescript const API_BASE_URL = process.env.LTCG_API_URL || "https://lunchtable.cards/api/agents"; ``` ```typescript const url = `${API_BASE_URL}${endpoint}`; const headers = { "Content-Type": "application/json", "Authorization": `Bearer ${this.apiKey}`, ...options.headers, }; const response = await fetch(url, { ...options, headers }); ``` Python configuration and request sink: ```python API_BASE_URL = os.getenv("LTCG_API_URL", "https://lunchtable.cards/api/agents") ``` ```python self.session = requests.Session() self.session.headers.update({ "Content-Type": "application/json", "Authorization": f"Bearer {api_key}", }) def _request(self, method: str, endpoint: str, body: Optional[Dict] = None) -> Any: """Make authenticated API request""" url = f"{API_BASE_URL}{endpoint}" try: if method == "GET": response = self.session.get(url) elif method == "POST": response = self.session.post(url, json=body) ``` ### Technical Analysis The examples trust `LTCG_API_URL` without validating its scheme, host, or port, while attaching the bearer API key to every request. A poisoned shell environment, modified `.env` file, compromised deployment configuration, or operator typo can therefore redirect the credential to an arbitrary server. Custom endpoints may be legitimate for development, but automatically forwarding production credentials to any configured origin violates least-destination principles. ### Attack Path 1. An attacker or compromised deployment process changes `LTCG_API_URL` to an attacker-controlled HTTPS endpoint. 2. The user starts one of the example agents with a vali ...[truncated 594 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Default to a fixed, trusted HTTPS origin. - Parse custom URLs and allowlist approved LTCG hostnames and ports. - Reject HTTP, embedded credentials, unexpected ports, and non-LTCG origins. - Require a separate explicit development flag before permitting custom origins. - Display the final credential destination and require confirmation for non-production configurations. - Do not automatically attach authorization headers after cross-origin redirects. - Separate test credentials from production credentials and scope keys to minimum required API permissions. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
examples/basic-agent.ts:513
Finding
Newly Issued API Keys Are Printed in Plaintext<![CDATA[ ## Vulnerability Details **File Locations**: - `examples/basic-agent.ts:513-538` - `examples/basic-agent.py:450-475` **Vulnerability Type**: Plaintext secret exposure through terminal and captured logs **Risk Level**: Medium ### Vulnerable Code TypeScript: ```typescript const data = await response.json(); console.log(`✅ Registration successful!`); console.log(` Agent ID: ${data.playerId}`); console.log(` API Key: ${data.apiKey}`); console.log(` Wallet: ${data.walletAddress || "pending"}`); console.log(`\n⚠️ SAVE YOUR API KEY - it won't be shown again!\n`); return data.apiKey; ``` The key is printed again by the main routine: ```typescript console.log("Add this to your .env file:"); console.log(`LTCG_API_KEY=${config.apiKey}\n`); ``` Python: ```python data = response.json() print("✅ Registration successful!") print(f" Agent ID: {data['playerId']}") print(f" API Key: {data['apiKey']}") print(f" Wallet: {data.get('walletAddress', 'pending')}") print("\n⚠️ SAVE YOUR API KEY - it won't be shown again!\n") return data["apiKey"] ``` The Python main routine also prints an export command containing the key: ```python print("Add this to your environment:") print(f"export LTCG_API_KEY={api_key}\n") ``` ### Technical Analysis The registration helpers print the complete bearer credential to standard output multiple times. Terminal multiplexers, CI logs, remote execution systems, support transcripts, shell recording tools, and centralized log collectors may retain standard output. The key must be delivered to the registering user once, but duplicating it in ordinary logs is not the minimum exposure necessary. ### Attack Path 1. A user runs an example without an existing `LTCG_API_KEY`. 2. The example registers a new agent. 3. The full key is printed to standard output twice. 4. A CI system, process supervisor, terminal recorder, or shared logging agent stores the output. 5. Another party with log access extracts the key and authenticate ...[truncated 303 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Avoid printing full API keys to normal standard output. - Provide an explicit one-time secure-output mode if displaying the key is unavoidable. - Write the key to a user-selected file created with owner-only permissions, such as mode `0600`. - Print only a masked prefix and suffix in subsequent messages. - Mark secret-bearing output for redaction in CI and deployment platforms. - Warn users not to run registration in shared terminals or captured build logs. - Support prompt-based or secret-manager-based storage rather than generating copy-and-paste shell commands. - Document immediate key rotation if terminal or CI output has been exposed. ]]>

T08 · Insecure Dependencies

Warning
Location
publish.sh:27
Finding
Publishing and Example Workflows Execute Unpinned Third-Party Components<![CDATA[ ## Vulnerability Details **File Locations**: - `publish.sh:27-32` - `.github/workflows/publish.yml:12-20, 34-36` - `examples/README.md:31, 151` **Vulnerability Type**: Unpinned dependency and CI action execution **Risk Level**: Medium ### Vulnerable Code Publishing script: ```bash if ! command -v clawhub &> /dev/null; then echo -e "${YELLOW}⚠️ ClawHub CLI not found. Installing...${NC}" npm install -g @clawhub/cli echo -e "${GREEN}✓ ClawHub CLI installed${NC}" fi ``` GitHub Actions workflow: ```yaml - name: Checkout code uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' registry-url: 'https://registry.npmjs.org' ``` ```yaml - name: Install ClawHub CLI run: npm install -g @clawhub/cli ``` Example commands: ```bash npx tsx basic-agent.ts ``` ```bash pip install requests ``` ### Technical Analysis The publishing flow installs the latest matching ClawHub CLI globally and immediately executes it in an authenticated publishing context. The documentation similarly uses unpinned `npx` and `pip` installations. GitHub Actions are pinned only to mutable major-version tags rather than immutable commit hashes. No evidence establishes that the referenced dependencies are currently malicious. The risk is that future registry compromise, account takeover, dependency confusion, or mutable-tag changes can alter the code executed after this Skill has been reviewed. ### Attack Path 1. An upstream package account, release channel, or mutable action tag is compromised or publishes a malicious update. 2. A user runs `publish.sh`, follows the example commands, or triggers the CI workflow. 3. The package manager or workflow resolves the changed component. 4. The third-party code executes with the user's or CI runner's permissions. 5. In the publishing workflow, malicious code may access repository content and credentials made available to subsequent authenticated publishing steps. ### Impa ...[truncated 403 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin `@clawhub/cli`, `tsx`, and Python dependencies to reviewed versions. - Commit lockfiles and use reproducible installation commands such as `npm ci`. - Avoid global installations and ad hoc `npx` downloads in privileged publishing flows. - Install reviewed dependencies locally and invoke their locked binaries. - Pin GitHub Actions to immutable full commit SHAs. - Use dependency integrity verification and automated vulnerability monitoring. - Separate validation from credential-bearing publishing jobs. - Apply least-privilege permissions to `GITHUB_TOKEN` and use short-lived, scoped publishing credentials. - Review dependency updates before allowing them into release workflows. ]]>
Vulnerability Patterns
  • 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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (42)

Tainted flow: 'API_BASE_URL' from os.getenv (line 44, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
"""Register a new agent and return API key"""
    print(f"Registering new agent: {name}")

    response = requests.post(
        f"{API_BASE_URL}/register",
        json={
            "name": name,
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

YARA rule 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Content
↑                             ↑
   └─────── 1. Register ────────→
              webhook URL

   ← ─ ─ ─ 2. It's your turn! ─ ─ ─
              (POST to your URL)

   → ─ ─ ─ 3. HTTP 200 OK ─ ─ ─ →

   (Bot makes move)

   ← ─ ─ ─ 4. Game ended! ─ ─ ─ ─
              (POST to your URL)
```

## Quick Start: Using webhook.site

The easiest way to test webhooks is webhook.site. It gives you a unique URL that captures all requests.

1. Visit https://webhook.site
2. You'll get a unique URL like `https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
3. Use this URL when registering your webhook below

## Step 1: Register Your Webhook

Register to receive turn notifications:

```bash
curl -X POST https://lunchtable.cards/api/game/webhooks \
  -H "Authorization: Bearer $LTCG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["turn_start", "turn_end", "game_end"],
    "url": "https:
Confidence
90% confidence
Finding
The YARA hit is not evidence of deliberate credential theft, but the document combines environment-based secrets, webhook registration, and repeated recommendation of a third-party capture endpoint in a way that can cause sensitive game traffic and signed webhook data to be sent to an external service. In the context of an agent skill, normalizing this pattern is dangerous because users may copy it directly into real deployments without understanding the disclosure and exposure risks.

Concealed Executable Artifact

High
Category
Supply Chain
Confidence
100% confidence
Finding
An executable nested in a document or hidden/disguised artifact can evade ordinary extension-based review while still being available to the skill at runtime.

Credential Access

High
Category
Privilege Escalation
Content
The skill requires one mandatory and several optional environment variables.

**Option A: Using .env file (Recommended)**

Create a `.env` file in the skill directory:
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
The skill requires one mandatory and several optional environment variables.

**Option A: Using .env file (Recommended)**

Create a `.env` file in the skill directory:
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### Manual:
```bash
# Remove installation directory
rm -rf /path/to/openclaw/skills/openclaw-skill

# Unregister from OpenClaw
openclaw skill unregister ltcg
Confidence
90% 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).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### Manual:
```bash
# Remove installation directory
rm -rf /path/to/openclaw/skills/openclaw-skill

# Unregister from OpenClaw
openclaw skill unregister ltcg
Confidence
90% 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).

Self-Modification

High
Category
Rogue Agent
Content
clawhub logs lunchtable-tcg
```

**Update Skill:**
```bash
# Update version in SKILL.md, package.json, .clawhub.json
./publish.sh
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared purpose is gameplay-related, but the code chunk does not implement any game logic or user-facing card game functionality. Instead, it is a deployment/publishing automation script for distributing the skill to ClawHub and optionally npm. These are materially different capabilities and represent a different primary purpose than the description. While build/release tooling can be part of a project, this specific code chunk's behavior is unrelated to playing the game itself, so the description does not accurately represent what the supplied code actually does.

Self-Modification

High
Category
Rogue Agent
Content
clawhub whoami              # Check user
clawhub submit .            # Submit skill
clawhub status SKILL        # Check status
clawhub update SKILL        # Update published skill
clawhub logs SKILL          # View logs

# OpenClaw
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Self-Modification

High
Category
Rogue Agent
Content
clawhub whoami              # Check user
clawhub submit .            # Submit skill
clawhub status SKILL        # Check status
clawhub update SKILL        # Update published skill
clawhub logs SKILL          # View logs

# OpenClaw
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Credential Access

High
Category
Privilege Escalation
Content
# Get agent name from args or generate one
    agent_name = sys.argv[1] if len(sys.argv) > 1 else f"PythonAgent-{int(time.time())}"

    # Get API key from environment or register
    api_key = os.getenv("LTCG_API_KEY")

    if not api_key:
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
console.log("No API key found in environment. Registering new agent...\n");
    config.apiKey = await registerAgent(config.name);

    console.log("Add this to your .env file:");
    console.log(`LTCG_API_KEY=${config.apiKey}\n`);
  }
Confidence
95% confidence
Finding
The script instructs the user to paste the live API key into a `.env` entry and echoes the full credential in the console. Although `.env` files are common, this pattern increases the chance of accidental exposure through committed files, local plaintext storage, screenshots, copied terminal output, or insecure workstation backups.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
```
POST   /api/game/webhooks         # Register webhook
GET    /api/game/webhooks         # List webhooks
DELETE /api/game/webhooks/:id     # Delete webhook
```

### Debugging APIs
Confidence
80% 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).

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
console.log(`Final LP - You: ${event.yourFinalLifePoints}, Opponent: ${event.opponentFinalLifePoints}`);
    }

    // Always respond with 200 to confirm receipt
    res.json({ success: true });

  } catch (error) {
Confidence
70% confidence
Finding
Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Session Persistence

Medium
Category
Rogue Agent
Content
### Getting an LTCG API Key

1. Visit https://lunchtable.cards
2. Sign in to your account (create one if needed)
3. Navigate to **Settings → API Keys**
4. Click **Generate New Key**
5. Copy the key immediately (format: `ltcg_xxxxx...`)
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.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
- Try: `npm install -g openclaw`

**Problem: "EACCES: permission denied"**
- Solution: Use `sudo npm install -g` (not recommended for production)
- Better: Fix npm permissions - see https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally

**Problem: "Module not found"**
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The installation guide instructs users to run `rm -rf /path/to/openclaw/skills/openclaw-skill`, which is a destructive file deletion command. Although it is part of uninstallation, the markdown does not include any explicit warning to verify the path carefully or note that the deletion is irreversible.

Session Persistence

Medium
Category
Rogue Agent
Content
```

2. **Document changes**
   - Add entry to CHANGELOG.md
   - Update README.md if needed

3. **Publish update**
Confidence
80% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
## Features

- **Game Creation & Management**: Create casual or ranked game lobbies with customizable settings
- **Real-time Game Interaction**: Join games, execute moves, and track game state
- **AI-Ready API**: Built for AI agents to understand and execute complex game sequences
- **Error Handling**: Comprehensive error messages and validation for invalid actions
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.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# Register for an API key (first time only)
curl -X POST https://lunchtable.cards/api/agents/register \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MyAIAgent",
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill clearly requires access to environment variables and outbound network calls, but it does not declare any explicit tool scope or permissions boundaries. In agent environments, missing scope declarations can cause overbroad execution privileges or make reviewers unaware that the skill will handle secrets and contact external services.

External Transmission

Medium
Category
Data Exfiltration
Content
Register your AI agent to receive an API key:

```bash
curl -X POST https://lunchtable.cards/api/agents/register \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MyAIAgent",
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The documentation includes realistic plaintext API key examples in environment variables and Authorization headers without prominent guidance that they are placeholders and must never be reused, logged, or committed. Users and agents may accidentally treat them as real credentials patterns, echo them in logs, or copy unsafe handling practices into automation.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The checklist instructs users to generate ClawHub and npm tokens and store them in GitHub Secrets, but it does not explicitly warn that these are sensitive credentials that must never be committed, shared, printed in logs, or reused insecurely. In a publishing workflow for an agent skill, these tokens can authorize package publication or account actions, so weak handling increases the risk of credential leakage and unauthorized releases.

Static analysis

Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
examples/advanced-agent.ts:29

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
examples/basic-agent.ts:26

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
examples/README.md:52

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scenarios/first-game.md:16

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
SKILL.md:53