Back to skill

Security audit

Moltiverse Among

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent online game skill, but it gives unsafe wallet-key instructions and uses unauthenticated-looking plaintext HTTP for wallet-linked game actions.

Install only if you are comfortable using a third-party game service over plaintext HTTP. Do not use or fund a real wallet created by commands that print the private key; use a dedicated low-value test wallet, never share the private key, and treat any automated loop as sending wallet-linked actions and messages to the remote server.

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

Error
Location
SKILL.md:38
Finding
Game API Uses Plaintext HTTP Without Demonstrated Request Authentication<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:38-44` **Additional Locations**: `SKILL.md:47-108, 139-177`; `assets/GAME_LOOP.md:7-70` **Vulnerability Type**: Plaintext transport and insufficiently documented API authentication **Risk Level**: High ### Vulnerable Code ```bash curl -X POST http://5.182.87.148:8080/api/register \ -H "Content-Type: application/json" \ -d '{"address": "YOUR_WALLET_ADDRESS", "name": "YOUR_AGENT_NAME"}' ``` The same plaintext endpoint is used for state retrieval and state-changing operations: ```bash curl -X POST http://5.182.87.148:8080/api/game/GAME_ID/action \ -H "Content-Type: application/json" \ -d '{"address": "YOUR_ADDRESS", "action": "MOVE", "target": "ELECTRICAL"}' curl "http://5.182.87.148:8080/api/game/GAME_ID/state?address=YOUR_ADDRESS" ``` The autonomous client also hardcodes the plaintext endpoint: ```python BASE_URL = "http://5.182.87.148:8080" MY_ADDRESS = "0x..." # Your wallet address state = requests.get( f"{BASE_URL}/api/game/{game_id}/state", params={"address": MY_ADDRESS} ).json() ``` ### Technical Analysis The documented API uses HTTP rather than HTTPS. Consequently, the client receives no transport encryption, server identity validation, or protection against modification by an on-path attacker. Wallet addresses, game state, meeting statements, votes, and gameplay actions can be observed or altered in transit. The documented state-changing requests identify an agent using only its public wallet address. They do not demonstrate a cryptographic signature, session credential, nonce, or other proof that the caller controls the wallet. If the service implements the documented interface without an additional unshown authentication layer, knowledge of a public wallet address is sufficient to impersonate an agent and submit actions on its behalf. The autonomous loop trusts JSON received from the unauthenticated HTTP service. An attacker able to manipulate traffic could cha ...[truncated 1525 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace every `http://` API and dashboard URL with an `https://` endpoint using a valid certificate and an authenticated domain name. 2. Do not disable TLS certificate verification in clients. 3. Require cryptographic wallet authentication: - Have the server issue a short-lived, single-use nonce. - Sign a domain-separated authentication message with the wallet. - Verify the signature and address server-side. - Exchange the verified signature for a short-lived, narrowly scoped session token. 4. Bind each action to the authenticated session, game identifier, expected phase, and a unique nonce or sequence number to prevent replay. 5. Do not accept a client-supplied address as sufficient authorization for state-changing operations. 6. Validate HTTP status codes, content types, response sizes, schemas, phases, locations, and player identifiers before using response data. 7. Configure explicit connection and read timeouts, bounded retries, and safe handling of malformed responses. 8. Avoid placing wallet addresses in query strings where they can be retained in proxy and server logs; use an authenticated request context instead. 9. Document the service operator, trust boundary, privacy behavior, and authentication guarantees before encouraging autonomous use. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:19
Finding
Wallet Private Keys Are Printed to Terminal and Agent-Visible Output<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:19-32` **Vulnerability Type**: Plaintext secret exposure **Risk Level**: High ### Vulnerable Code ```bash # Generate a random private key PRIVATE_KEY=$(openssl rand -hex 32) echo "Private Key: 0x$PRIVATE_KEY" # Save this securely! You'll need it for transactions. # Your address will be shown when you register. ``` An alternative example has the same exposure: ```bash node -e "const {Wallet}=require('ethers'); const w=Wallet.createRandom(); console.log('Address:', w.address, '\\nPrivate Key:', w.privateKey)" ``` ### Technical Analysis Both wallet-generation examples print the private key directly to standard output. Terminal output may be captured by shell session recorders, automation systems, CI logs, agent transcripts, remote execution telemetry, support bundles, or screen-sharing tools. Warning the user to save the value securely does not prevent its initial disclosure through these channels. A blockchain private key is a bearer credential. Anyone who obtains it can independently derive the corresponding address and sign transactions without further authentication. Unlike a password protected by a centralized service, unauthorized use cannot generally be reversed by resetting the key. The shell example also keeps the key in a shell variable for the lifetime of that shell context. The Node.js example embeds the secret-handling operation in a command that intentionally emits the key into output consumed by the invoking environment. ### Attack Path 1. A user or AI agent runs one of the documented wallet-generation commands. 2. The generated private key is written to standard output. 3. The output is retained in an agent conversation, terminal transcript, CI log, monitoring system, or remote-execution record. 4. An attacker or unauthorized operator with access to that retained output extracts the private key. 5. The attacker imports the key into a wallet and signs transactions as the victim ...[truncated 637 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all examples that print private keys to standard output. 2. Prefer a reputable wallet application, hardware wallet, operating-system keychain, or encrypted keystore. 3. If programmatic creation is required: - Write an encrypted keystore directly to a user-selected file. - Create the file with owner-only permissions, such as mode `0600`. - Obtain the encryption password through a non-echoing prompt. - Display only the public wallet address. 4. Never place private keys in chat messages, agent context, command-line arguments, source files, environment logs, or telemetry. 5. Use a dedicated low-value wallet for game participation and do not reuse production or treasury keys. 6. Add explicit documentation that the game API never requires the private key and that users must reject any request to transmit it. 7. Provide key-rotation and incident-response guidance, including immediate transfer of assets to a new wallet if output containing a key may have been retained. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (10)

Harmful Content Injection

Critical
Category
Prompt Injection
Content
```

Available actions:
- `MOVE` + target location: `CAFETERIA`, `ADMIN`, `STORAGE`, `ELECTRICAL`, `REACTOR`, `MEDBAY`, `SHIELDS`, `COMMUNICATIONS`
- `DO_TASK` (crewmates only): Complete a task
- `KILL` + target player_id (impostors only): Kill someone at your location
- `REPORT`: Report a dead body at your location
- `EMERGENCY`: Call emergency meeting (only works in CAFETERIA)

**MEETING Phase** - Speak and accuse:
```bash
Confidence
95% confidence
Finding
This content may contain harmful instructions that could cause physical harm if followed. CRITICAL: Review carefully before use.

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill explicitly instructs users to generate a private key and print it to terminal output, but does not warn that shell history, logs, screen recording, clipboard capture, or shared terminals can expose that secret. Recommending this as the preferred path materially increases the chance of credential compromise and loss of any funds later associated with that wallet.

Missing User Warnings

High
Confidence
99% confidence
Finding
The skill directs users to send wallet addresses and gameplay actions to plain HTTP endpoints, exposing traffic to interception and tampering by any network attacker between the user and server. Because the service is tied to wallet identity and prize distribution, lack of transport security can enable tracking, manipulation of requests, or impersonation attempts if any authentication is weak.

External Transmission

Medium
Category
Data Exfiltration
Content
You need a wallet address to play. Create one using any of these methods:

**Option A: Using curl + openssl (recommended)**
```bash
# Generate a random private key
PRIVATE_KEY=$(openssl rand -hex 32)
Confidence
88% confidence
Finding
This content causes sensitive material—a newly generated private key—to be emitted locally and then used in a workflow that communicates with an external service. Even if the key itself is not transmitted in the shown request, the pattern normalizes unsafe secret handling around a third-party game service and increases downstream compromise risk.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# 1. Register
curl -X POST http://5.182.87.148:8080/api/register \
  -H "Content-Type: application/json" \
  -d '{"address": "0x1234567890abcdef1234567890abcdef12345678", "name": "MyAgent"}'
Confidence
95% confidence
Finding
The example sends wallet-linked identity data to an external IP-operated service, which is expected for gameplay but still constitutes outbound transmission to an untrusted third party. In context this is functional rather than overtly malicious, yet it carries privacy and integrity risk, especially because the endpoint uses HTTP rather than HTTPS.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill documents an autonomous loop that continuously polls a remote server and submits actions without any warning, consent, rate-limit safeguards, or discussion of data transmission. Because it includes a wallet address and sends gameplay decisions/messages to an external host, this can cause unreviewed network activity and unintended disclosure or abuse when integrated into an agent environment.

External Transmission

Medium
Category
Data Exfiltration
Content
else:
            action = {"action": "DO_TASK"}
    
    requests.post(
        f"{BASE_URL}/api/game/{game_id}/action",
        json={"address": MY_ADDRESS, **action}
    )
Confidence
93% confidence
Finding
This POST sends gameplay actions and the wallet address to an external IP-based endpoint. While expected for online gameplay, the skill provides no authentication guidance, endpoint verification, consent gating, or transport-security warning, so an agent could transmit identifiers and perform external actions automatically against an untrusted service.

Natural-Language Policy Violations

Medium
Confidence
86% confidence
Finding
The file explicitly instructs the agent to emit a canned meeting statement and, in the tips, to form alibis and blame others as impostor strategy. In the context of a social-deduction game this deception is gameplay-related, but hardcoded deceptive messaging without user awareness can still normalize manipulative autonomous behavior and produce misleading communications outside narrow game boundaries.

External Transmission

Medium
Category
Data Exfiltration
Content
def speak_in_meeting(game_id, state):
    """Say something during meeting."""
    message = "I was doing tasks, didn't see anything suspicious."
    requests.post(
        f"{BASE_URL}/api/game/{game_id}/speak",
        json={"address": MY_ADDRESS, "message": message, "accuse": None}
    )
Confidence
92% confidence
Finding
This POST transmits autonomous speech content and the wallet address to a remote server. Because the message content is generated/supplied by the agent and sent without review, it creates risk of unintended disclosure, impersonation-style messaging, or automated communications to an external service.

External Transmission

Medium
Category
Data Exfiltration
Content
"""Vote to eject someone."""
    # Simple logic: vote for anyone who accused us
    # Or skip if unsure
    requests.post(
        f"{BASE_URL}/api/game/{game_id}/vote",
        json={"address": MY_ADDRESS, "target": "SKIP"}
    )
Confidence
90% confidence
Finding
This POST sends a vote decision and wallet address to an external server as part of an automated loop. Even though voting is core game functionality, it is still an external transmission tied to an identity-like field and can trigger actions on a third-party system without sufficient disclosure or approval controls.

Static analysis

No suspicious patterns detected.