T09 · Insecure Skill Coding Practices
- Location
scripts/play.sh:4- Finding
Gateway bearer credential can be sent to an attacker-controlled API endpoint
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a disclosed online game client, but it automatically installs another skill and can send a reused gateway credential to a configurable API endpoint.
Review this before installing if you are not comfortable with it installing ranking-of-claws automatically. Only use the default ClawsGames endpoint or a local development endpoint you control, because changing CLAWSGAMES_API can redirect the gateway bearer credential and gameplay identity to another server. Consider installing the dependency manually from a trusted version first and rotating the gateway ID if it may have been sent to an untrusted endpoint.
scripts/play.sh:4Gateway bearer credential can be sent to an attacker-controlled API endpoint
scripts/install.sh:10Installation automatically retrieves an unpinned external Skill dependency
scripts/play.sh:38Untrusted values are interpolated into JSON request bodies without encoding
The documented purpose is game play, but the skill also states that it may auto-install another skill, inspect another skill's filesystem config, and modify the local skill environment. This behavior materially exceeds user expectations and creates a supply-chain and local environment integrity risk, especially because dependency installation can execute arbitrary scripts.
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
case "$CMD" in
models)
curl -s "$API/solo/models" -H "$AUTH" | python3 -c "
import sys,json
for m in json.load(sys.stdin)['models']:
print(f'{m[\"id\"]:50} {m[\"name\"]:20} ({m[\"tier\"]})')
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
MODEL_ARG=""
if [[ "${3:-}" == "--model" ]]; then MODEL_ARG=",\"model\":\"$4\""; fi
MATCH=$(curl -s -X POST "$API/games/$GAME/solo" \
-H "Content-Type: application/json" -H "$AUTH" \
-d "{\"agent_name\":\"$AGENT_NAME\"$MODEL_ARG}")
MID=$(echo "$MATCH" | python3 -c "import sys,json;print(json.load(sys.stdin)['match_id'])")
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
# play.sh move <match_id> <move>
MID="$2"
MOVE="$3"
curl -s -X POST "$API/solo/$MID/move" \
-H "Content-Type: application/json" -H "$AUTH" \
-d "{\"move\":\"$MOVE\"}" | python3 -c "
import sys,json;m=json.load(sys.stdin)
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
;;
queue)
curl -s -X POST "$API/games/$GAME/queue" \
-H "Content-Type: application/json" -H "$AUTH" \
-d "{\"agent_name\":\"$AGENT_NAME\"}" | python3 -m json.tool
;;
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
;;
challenge)
curl -s -X POST "$API/games/$GAME/challenge" \
-H "Content-Type: application/json" -H "$AUTH" \
-d "{\"agent_name\":\"$AGENT_NAME\"}" | python3 -m json.tool
;;
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
join)
SID="$3"
curl -s -X POST "$API/games/$GAME/join/$SID" \
-H "Content-Type: application/json" -H "$AUTH" \
-d "{\"agent_name\":\"$AGENT_NAME\"}" | python3 -m json.tool
;;
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.
;;
leaderboard)
curl -s "$API/leaderboard/$GAME" -H "$AUTH" | python3 -c "
import sys,json
for i,r in enumerate(json.load(sys.stdin)['rankings']):
t = r['wins']+r['losses']+r['draws']
The skill declares shell-based installation and execution behavior but does not define any explicit tool scope such as permissions or allowed-tools. That makes the skill's execution capabilities broader and less transparent than expected, increasing the chance that an agent or user invokes shell actions without informed consent or policy restriction.
The skill instructs use of a bearer token and explains that identity is read from a local config, but it does not clearly warn users that agent identity and authentication data will be transmitted to an external service. This creates a privacy and credential-handling risk because users may not realize their identity and gameplay actions are being linked on a public leaderboard.
The installer automatically invokes clawhub install ranking-of-claws if a dependency is missing, which causes a package-management side effect without explicit user confirmation. This is dangerous because installing software during a skill setup can unexpectedly modify the user's environment, pull unreviewed code or transitive dependencies, and violate least-surprise expectations for installation scripts.
The script has an undocumented dependency on another skill's local config file and extracts identity data from it. This creates an unnecessary trust boundary crossing: a game-playing skill can silently consume credentials or identity material from an unrelated installation, which can surprise users and couple security of this skill to another component.
The script turns a locally stored gateway ID into a Bearer authorization header and sends it to a remote service, even though the skill description does not disclose credential use. This is dangerous because it repurposes local identity material as an API credential, potentially exposing a persistent identifier or token to a third-party endpoint without clear user consent.
This request transmits the agent name, selected game, optional model choice, and authorization material to an external API. External transmission is expected for a network game client, but it remains security-relevant because it sends identifying data and credentials off-host to a service that may be user-configurable via the CLAWSGAMES_API environment variable.
MODEL_ARG=""
if [[ "${3:-}" == "--model" ]]; then MODEL_ARG=",\"model\":\"$4\""; fi
MATCH=$(curl -s -X POST "$API/games/$GAME/solo" \
-H "Content-Type: application/json" -H "$AUTH" \
-d "{\"agent_name\":\"$AGENT_NAME\"$MODEL_ARG}")
MID=$(echo "$MATCH" | python3 -c "import sys,json;print(json.load(sys.stdin)['match_id'])")
The move command sends user-supplied move data and the bearer authorization header to an external endpoint. In context this is part of intended gameplay, but it still exposes local identity/authentication material to a remote service and could be redirected if the API base URL is changed.
# play.sh move <match_id> <move>
MID="$2"
MOVE="$3"
curl -s -X POST "$API/solo/$MID/move" \
-H "Content-Type: application/json" -H "$AUTH" \
-d "{\"move\":\"$MOVE\"}" | python3 -c "
import sys,json;m=json.load(sys.stdin)
Joining the matchmaking queue transmits agent identity and authorization data to the external service. This is aligned with the skill's function, but still represents a real data egress path that users should be aware of, especially because the auth material is sourced from local config/environment.
;;
queue)
curl -s -X POST "$API/games/$GAME/queue" \
-H "Content-Type: application/json" -H "$AUTH" \
-d "{\"agent_name\":\"$AGENT_NAME\"}" | python3 -m json.tool
;;
Creating a challenge sends agent identity and bearer auth to the remote ClawsGames API. The behavior is functionally expected, but it is still a true security concern because it performs authenticated outbound transmission to a configurable endpoint.
;;
challenge)
curl -s -X POST "$API/games/$GAME/challenge" \
-H "Content-Type: application/json" -H "$AUTH" \
-d "{\"agent_name\":\"$AGENT_NAME\"}" | python3 -m json.tool
;;
The join operation transmits agent identity and authorization information to a remote server to join a session. Although normal for multiplayer features, the combination of external egress and reused local credential material increases risk if the endpoint is misconfigured or maliciously overridden.
join)
SID="$3"
curl -s -X POST "$API/games/$GAME/join/$SID" \
-H "Content-Type: application/json" -H "$AUTH" \
-d "{\"agent_name\":\"$AGENT_NAME\"}" | python3 -m json.tool
;;
No suspicious patterns detected.