T09 · Insecure Skill Coding Practices
- Location
SKILL.md:41- Finding
Game API Communication Uses Unencrypted HTTP
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This documentation-only game skill is not malicious, but it needs review because it tells users to print wallet private keys and use an unauthenticated HTTP game API.
Review before installing or using. Do not use a wallet with real funds or unrelated assets, do not paste private keys into an agent or terminal transcript, and assume any key printed in logs may be exposed. The game API examples use unencrypted HTTP, so wallet addresses, names, messages, votes, and actions can be observed or altered in transit.
SKILL.md:41Game API Communication Uses Unencrypted HTTP
SKILL.md:18Wallet Private Keys Are Printed to Standard Output
This content may contain harmful instructions that could cause physical harm if followed. CRITICAL: Review carefully before use.
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
The skill instructs users to generate and handle a blockchain private key and to submit the associated wallet address to a third-party service, but it provides no explicit warning about key custody, phishing risk, wallet segregation, or privacy implications. In practice, this can lead users to expose or mishandle sensitive credentials, especially because the workflow is framed as a simple prerequisite to gameplay.
This section encourages local generation and display of a private key as part of a workflow tied to an external service, which increases the chance that users will mishandle, log, or reuse sensitive credentials. Although the key is not directly transmitted in the shown command, the skill normalizes risky secret handling without adequate safeguards.
You need a wallet address to play. Create one using any of these methods:
Option A: Using curl + openssl (recommended)
# Generate a random private key
PRIVATE_KEY=$(openssl rand -hex 32)
All API examples use plain HTTP to a remote IP address, meaning registration data, wallet addresses, game actions, and server responses are sent without transport encryption or authenticity guarantees. This enables interception, tampering, replay, or redirection by any network attacker between the user and the service.
The example transmits a wallet address and agent identifier to a remote service, which is an external data transmission. While expected for gameplay, it still has privacy and integrity implications, especially because the endpoint uses plaintext HTTP and the remote host is an IP address rather than a clearly authenticated domain.
# 1. Register
curl -X POST http://5.182.87.148:8080/api/register \
-H "Content-Type: application/json" \
-d '{"address": "0x1234567890abcdef1234567890abcdef12345678", "name": "MyAgent"}'
The skill documents an autonomous loop that continuously polls a remote server and sends the user's wallet address plus gameplay actions/messages without any warning about ongoing network activity, persistence, or privacy implications. In a wallet-linked agent context, omission of these disclosures can cause users to unknowingly authorize sustained external communication and behavioral automation.
This POST sends the wallet address and chosen game action to an external server over plain HTTP to a hard-coded IP address, exposing metadata and allowing interception or tampering in transit. Because the action loop is autonomous, it can repeatedly disclose identity-linked activity and perform unintended remote actions without interactive confirmation.
else:
action = {"action": "DO_TASK"}
requests.post(
f"{BASE_URL}/api/game/{game_id}/action",
json={"address": MY_ADDRESS, **action}
)
This POST transmits the wallet address and meeting message to an external service, again over plain HTTP, which risks eavesdropping, manipulation, and collection of identity-linked communications. In this skill's context, autonomous generation and transmission of speech increases the chance of users unknowingly broadcasting content or metadata on a continuous basis.
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}
)
This POST sends a vote decision together with the wallet address to a remote endpoint over plain HTTP, creating exposure of identity-associated decisions and enabling network attackers to observe or alter requests. Because this is part of an unattended loop, the skill can repeatedly take externally visible actions on behalf of the user without per-action acknowledgment.
"""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"}
)
No suspicious patterns detected.