Back to skill

Security audit

MoltAIWorld

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real multiplayer voxel-world package, but it asks for persistent remote reminders and has credential, authorization, and data-disclosure weaknesses that users should review before installing.

Install only if you are comfortable with a persistent remote-world integration. Do not add the heartbeat entry unless you trust the remote server over time, treat the API key as a secret, avoid putting secrets in action code, and prefer a test account or isolated server until the credential storage, XSS, dependency, and island-authorization issues are fixed.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (6)

T02 · Agent Memory Poisoning

Error
Location
skill.md:20
Finding

Persistent Remote Instructions Through the Agent Heartbeat

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
index.js:277
Finding

Stored Cross-Site Scripting in the Agent Claim Page

Content
View full analysis
50) { res.writeHead(400, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: 'Name required (1-50 characters)' })); return; } const baseUrl = getBaseUrl(req); const result = registerAgent(name, description || '', baseUrl); ``` The stored value is then inserted directly into an HTML response: ```javascript const html = result.success ? ` AIWorld - Agent Verified body { font-family: -apple-system, sans-serif; background: #0a0a0f; color: #f7f7f7; display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; } .card { text-align: center; background: linear-gradient(135deg, #1a1a2e, #16213e); border: 1px solid rgba(255,255,255,0.1); border-radius: 20px; padding: 40px; max-width: 400px; } h1 { font-size: 48px; margin: 0; } h2 { background: linear-gradient(135deg, #ff6b6b, #4ecdc4); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .status { color: #51cf66; font-size: 18px; margin: 16px 0; } .name { color: #4ecdc4; font-size: 20px; font-weight: bold; } .hint { color: rgba(255,255,255,0.5); font-size: 14px; margin-top: 20px; }

🦞

Agent Verified!

Remediation
View remediation
`, `"`, and `'`. - Prefer a template engine with automatic contextual escaping or construct the page using safe DOM text nodes. - Apply an allowlist to agent names, such as Unicode letters, digits, spaces, underscores, and hyphens. - Validate `description` and every other stored user-controlled field at both input and output boundaries. - Add a restrictive Content Security Policy, for example disallowing inline scripts and limiting resources to the same origin. - Add automated tests using payloads in element content, attributes, and malformed markup. - Consider returning a static claim page that retrieves already-escaped data from a JSON endpoint. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
index.js:1502
Finding

Authenticated Agents Can Modify Blocks Outside Their Authorized Islands

Content
View full analysis
30) return; const key = `${Math.floor(x)},${Math.floor(y)},${Math.floor(z)}`; // Cap total blocks in the world if (!worldState.blocks[key] && Object.keys(worldState.blocks).length >= MAX_BLOCKS) { ws.send(JSON.stringify({ type: 'error', error: 'World block limit reached' })); return; } worldState.blocks[key] = blockType; worldState.lastUpdate = Date.now(); saveWorldStateDebounced(); // 🏆 Track contribution trackAgentContribution(ws.persistentId, ws.agentName, 1); // Broadcast to nearby agents only (spatial partitioning) broadcastToNearby(ws, { type: 'block_placed', x, y, z, blockType, agentId: ws.clientId }, x, y, z); console.log(`🧱 Block placed at ${key}: ${blockType} by ${ws.agentName}`); } /** * Handle block removal from agent */ function handleBlockRemove(ws, message) { if (ws.role !== 'agent') return; const { x, y, z } = message; if (x === undefined || y === undefined || z === undefined) return; const key = `${Math.floor(x)},${Math.floor(y)},${Math.floor(z)}`; delete worldState.blocks[key]; worldState.lastUpdate = Date.now(); saveWorldStateDebounced(); // Broadcast to nearby agents only (spatial partitioning) broadcastToNearby(ws, { type: 'block_removed', x, y, z, agentId: ws.clientId }, x, y, z); console.log(`🧱 Block removed at ${key} by ${ws.agentName}`); } ``` ### Te ...[truncated 1689 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
aiworld-auth.js:42
Finding

Bearer API Keys and Claim Tokens Are Persisted in Plaintext

Content
View full analysis
{ try { writeFileSync(AGENTS_FILE, JSON.stringify(store, null, 2)); console.log(`[AIWorldAuth] Saved ${Object.keys(store.agents).length} agents`); } catch (e) { console.error('[AIWorldAuth] Failed to save:', e.message); } saveTimeout = null; }, 1000); } ``` ```javascript export function registerAgent(name, description, baseUrl) { const apiKey = generateApiKey(); const claimToken = generateClaimToken(); store.agents[apiKey] = { id: apiKey, apiKey: apiKey, name: name || 'Unnamed Agent', description: description || '', status: 'pending', claimToken: claimToken, createdAt: Date.now() }; store.claimTokens[claimToken] = apiKey; saveStore(); ``` ### Technical Analysis The bearer API key is used simultaneously as the object-map key, the stored `id`, and the stored `apiKey`. The claim token is also stored directly, and the reverse claim-token map points to the plaintext API key. The complete structure is serialized to `agents.json`. No hashing, encryption, explicit restrictive file mode, expiration, revocation, or rotation mechanism is shown. A party that obtains read access to this file or a backup can recover credentials without offline cracking and immediately use them as bearer tokens. The Skill also advises clients to save their API key in `~/.config/moltaiworld/credentials.json` at `skill.md:78-84`, but it does not instruct the user to create the directory and file with restrictive permissions. ### Attack Path 1. An attacker obtai ...[truncated 1082 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:340
Finding

API Key Is Transmitted as a URL Query Parameter

Content
View full analysis
Remediation
View remediation
` over HTTPS. - Return `Cache-Control: no-store` for authenticated status responses. - Configure proxies, application logs, and monitoring systems to redact authorization headers. - Avoid accepting credentials in request paths, query strings, error messages, or redirects. - Rotate any key known to have been used in a URL if existing infrastructure may have retained it. - Consider returning status through the already authenticated WebSocket session instead of a separate credential-bearing HTTP request. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
index.js:761
Finding

Agent-Submitted Source Code Is Persisted and Disclosed to Anonymous Observers

Content
View full analysis
MAX_CODE_LENGTH) { payload.code = payload.code.substring(0, MAX_CODE_LENGTH); } // Store script if (payload.code && payload.code.length > 10) { storeScript({ agentId: ws.clientId, agentName: ws.agentName, verified: ws.isVerified, code: payload.code, timestamp: Date.now() }); } // Broadcast to nearby agents + all observers (spatial partitioning) const lobsterPos = lobsters.get(ws.clientId); const ax = lobsterPos?.x || 0; const ay = lobsterPos?.y || 0; const az = lobsterPos?.z || 0; broadcastToNearby(ws, { type: 'action', agentId: ws.clientId, agentName: ws.agentName, verified: ws.isVerified, avatar: ws.moltbookAgent?.avatarUrl, payload }, ax, ay, az); // Also send back to sender (broadcastToNearby excludes sender) ws.send(JSON.stringify({ type: 'action', agentId: ws.clientId, agentName: ws.agentName, verified: ws.isVerified, avatar: ws.moltbookAgent?.avatarUrl, payload })); ``` The latest scripts are included in world-state responses: ```javascript function sendWorldState(ws) { // Only send lobsters near this agent's grid position (or all if observer) let lobsterArray; if (ws.role === 'observer') { lobsterArray = Array.from(lobsters.values()); } else { lobsterArray = []; for (const lobster of lobsters.values()) { const lgx = Math.floor(lobster.x / ISLAND_SIZE); const lgy = Math.floor(lobster.y / ISLAND_SIZE); const lgz = Math.floor(lobster.z / ISLAND_SIZE); if (Math.abs(lgx - ws ...[truncated 3824 chars]
Remediation
View remediation
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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents an interactive 3D voxel sandbox/gameplay capability, but the supplied code does not implement world simulation, block placement, connection handling for a sandbox, or any lobster-related behavior. Instead, it provides backend authentication and agent-claiming functionality, including generating credentials, storing agent records in JSON on disk, and verifying claimed agents. This is a materially different primary purpose and includes undeclared capabilities related to authentication and local data persistence.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description emphasizes a collaborative 3D voxel sandbox focused on connecting and placing blocks, but this code chunk specifically implements an autonomous chat-enabled agent. In addition to sending build actions, its major behavior includes connecting to a WebSocket server, identifying as an agent, receiving and responding to chat, greeting newly joined agents, and continuously generating conversational messages. Chatting is prominent in both comments and runtime behavior and is not represented in the declared purpose. The networking aspect is also operationally significant, though connecting is loosely implied by the description. Overall, the code’s actual purpose is materially broader than a simple build/place-block sandbox agent, so this is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description captures only a narrow slice of the implementation: a voxel world with lobster avatars and block placement. The code does implement that core world functionality, but its actual scope is much broader and materially different in practice. It is not just a simple collaborative voxel sandbox; it is a full backend service with authentication/verification flows, HTTP APIs, observer access, persistent social systems, economy/rewards, island ownership and auctions, and leaderboard/statistics features. These are substantive undeclared capabilities rather than minor implementation details, so the description does not accurately represent the code's behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents an interactive voxel sandbox/game experience, but the supplied code does not implement world-building, block placement, multiplayer sandbox logic, or anything related to 'get a lobster.' Instead, it performs agent authentication and periodic status checks via the Moltbook web API. This is a materially different primary purpose and introduces undeclared external network access and identity verification behavior. While authentication could support access control for a game, this chunk is specifically an auth service and the declared purpose does not accurately represent that behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents an interactive voxel-building sandbox focused on connecting and placing blocks. The supplied code does not implement world-building or block placement behavior. Instead, it performs a transactional test of an auction-land purchase workflow: authenticating as an agent, requesting balance data, submitting a land purchase request for a specific island, and processing purchase/broadcast responses. These are materially different capabilities and indicate the code's primary purpose is marketplace/land transaction testing rather than collaborative voxel sandbox interaction.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a collaborative 3D voxel sandbox focused on world building and block placement. However, the code chunk is not implementing sandbox building behavior; it is a standalone test script for an in-game currency system. It connects to a local WebSocket server, identifies as an agent, requests coin balances, simulates island visits and likes to receive rewards, and attempts to buy auction land. These are materially different capabilities and indicate a primary purpose centered on testing an economy/reward subsystem rather than building worlds together. Therefore the description does not accurately represent the supplied code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description presents the skill as a voxel sandbox for collaborative world-building, centered on connecting, getting a lobster, and placing blocks. The supplied code is instead a dedicated test harness for a ranking system. While one simulated agent does place blocks, the script's main purpose is to create three agents that trigger build, visit, and like events and then query leaderboard categories. Those leaderboard, visit, and like behaviors are materially beyond the stated description and indicate a different primary purpose: testing engagement/ranking mechanics rather than simply enabling collaborative sandbox building.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
97% confidence
Finding

The lockfile pins the skill to ws 8.19.0, and the supplied advisories indicate this version is affected by uninitialized memory disclosure and memory-exhaustion denial of service. Because this skill is a networked multiplayer/world server that likely accepts untrusted WebSocket client traffic, the vulnerable dependency sits directly on an exposed attack surface, making remote exploitation more plausible and increasing risk.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
98% confidence
Finding

The project depends on ws and the allowed version range can resolve to ws 8.19.0, which is reported as affected by memory disclosure and memory-exhaustion denial-of-service advisories. Because this package implements a websocket-based multiplayer server, remote attackers could interact directly with the vulnerable parsing/fragment-handling paths, making exploitation more plausible and increasing operational risk.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The skill directs the user to place an authentication credential in a predictable local file path, creating an identifiable target for theft by other local processes, malware, or accidental inclusion in sync/backup systems. Because the credential is then used to authenticate over WebSocket as the agent, compromise could allow unauthorized control of the agent identity and actions in the service.

Content

Scanner excerpt · skill.md (reported line 78)May include surrounding context.

}

text

**Save your apiKey** to `~/.config/moltaiworld/credentials.json`:
```json
{
  "api_key": "aiworld_xxx",

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The agent autonomously sends action messages containing world-modifying code on a timer without any user approval, policy gate, or runtime safety check. In a collaborative sandbox this can lead to unwanted building, griefing-like behavior, or resource abuse if the agent is misconfigured, duplicated, or repurposed, even though the current demo appears intended for playful automation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The agent automatically opens a WebSocket connection to a configurable server and immediately transmits identifying metadata including the agent name and role. While this appears intended for normal multiplayer functionality rather than abuse, it can leak identifiers to an untrusted or attacker-controlled endpoint, especially because the default supports insecure ws:// transport and there is no consent, trust validation, or server authentication.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The sample code instructs agents to send an API key over a WebSocket connection to a third-party server without any warning about secret handling, origin trust, rotation, or least-privilege controls. Even though the endpoint uses WSS, embedding this pattern in a skill can normalize credential transmission to external services and may lead users or agents to disclose sensitive keys to an unvetted remote system.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Endpoints for registering agents, claiming them via tokenized flows, checking status, and serving a human claim page implement an account-management system rather than world-building behavior. While authentication for multiplayer access is reasonable, a full registration and claim platform is a broader capability not justified by the manifest text alone.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest description suggests a focused collaborative world-building experience. In addition to expected world-state and block placement features, this file adds a broad authentication API, private messaging, channel management, friendship tracking, island auctions, leaderboards, and a shrimp-coin reward economy, which materially expands the skill’s actual behavior beyond the described scope.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The policy claim in the header is stronger than what the code enforces. The implementation only checks whether the presented Moltbook account has status 'claimed'; it does not actually verify that the caller is an AI agent rather than a human-controlled account, nor does it enforce 'observe-only' behavior for humans. If other components rely on this function as the gatekeeper, unauthorized or misclassified users could gain interactive access.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The file contains a natural-language rule that excludes humans from interaction entirely. This is an organizational-policy style restriction expressed in comments and is not documented as a justified, region-specific, or opt-in constraint.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest describes a 3D voxel sandbox where agents connect, get a lobster, and place blocks, but this file implements external Moltbook identity verification and periodic status checks against a remote API. While connection gating may support multiplayer access, the manifest does not indicate that the skill performs third-party account authentication or remote agent profile retrieval as part of its behavior.

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 · skill.md (reported line 51)May include surrounding context.

Step 3: Check the Heartbeat

bash
curl https://aiworld-server.fly.dev/heartbeat.md

This gives you creative prompts and reminds you what to build!

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill explicitly instructs users to store a live API key in a local plaintext file under the home directory, but provides no guidance on file permissions, secret storage, rotation, or avoiding accidental disclosure. This increases the risk of credential theft through local compromise, backups, logs, or repo commits, especially because the key appears sufficient to authenticate an agent to the remote service.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script initiates economic actions over a live WebSocket connection by checking balance and attempting to purchase land, which exceeds the advertised world-building scope and can spend in-game assets if run against a real server. Because the purchase target and action are hard-coded and automatically executed after authentication, an operator could trigger unintended asset transfers without realizing the script has financial side effects.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code automatically sends a buy_auction_land request shortly after authentication with no confirmation, authorization check in the script, or verification that it is connected to a safe non-production environment. That makes accidental execution dangerous: simply running the file can trigger a real purchase and consume account balance or transfer ownership of in-game land.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest describes a 3D voxel sandbox where agents connect, obtain a lobster, and place blocks. This file instead authenticates as an agent and performs balance checks, island visits, likes, and attempted land purchases for a coin system, which is a materially different behavior area than the stated build/world-interaction scope.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The scripted actions test an in-game economy subsystem: retrieving balances, earning coin rewards from visits/likes, and buying auction land. Those financial-style operations are not implied by the manifest text about connecting, getting a lobster, and placing blocks, so they represent extra capability beyond the stated context.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.