Back to skill

Security audit

文字游戏机免费版

Security checks for vulnerabilities and agentic risk

Overview

The skill is a text-game helper, but it asks for broad execution authority and documents local persistence in an under-scoped way that users should review before installing.

Install only if you are comfortable granting a text-game skill command execution access and local file persistence. Avoid using sensitive personal information in prompts or saved game state, and prefer a version that removes broad exec permission, narrows triggers/tags, clearly explains LLM/network behavior, and validates save-slot paths.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:276
Finding

Path Traversal in Save and Load Slot Handling

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 276–287
Vulnerability Type: Path traversal through an unvalidated save-slot identifier
Risk Level: Medium

python
def save_game(game_state, slot="auto"):
    """保存游戏进度"""
    save_dir = Path("~/.text-game/saves").expanduser()
    save_dir.mkdir(parents=True, exist_ok=True)
    save_file = save_dir / f"{slot}.json"
    save_file.write_text(json.dumps(game_state, ensure_ascii=False, indent=2))
# .
def load_game(slot="auto"):
    """读取游戏进度"""
    save_file = Path("~/.text-game/saves").expanduser() / f"{slot}.json"
    if save_file.exists():
        return json.loads(save_file.read_text())
    return None

Technical Analysis

The slot value is interpolated directly into a filesystem path without validation or canonical containment checking. Python's pathlib path-composition behavior permits traversal components such as ../. An absolute path supplied as the right-hand operand can also replace the intended base path.

Consequently, the resulting save_file is not guaranteed to remain beneath ~/.text-game/saves. The .json suffix limits target selection to paths ending in that suffix, but it does not prevent access to JSON files elsewhere on the filesystem.

This is an insecure coding pattern presented by the skill for agents or users to implement. Exploitability depends on an attacker being able to control the slot argument in an implementation based on this example.

Attack Path

  1. A victim implements or executes the documented save_game or load_game logic.
  2. The attacker supplies a crafted slot identifier containing traversal components, such as ../../other/config.
  3. The application constructs a path equivalent to ~/.text-game/saves/../../other/config.json.
  4. No normalization or containment validation rejects the escaped path.
  5. For load_game, the process reads and parses the external JSON file if it ...[truncated 713 chars]
Remediation
View remediation

Remediation Suggestions

  • Restrict slot identifiers to a conservative allowlist, for example ^[A-Za-z0-9_-]{1,64}$.
  • Resolve both the save directory and candidate file path, then verify that the candidate remains within the resolved save directory.
  • Reject absolute paths, path separators, . components, and .. components.
  • Use explicit UTF-8 encoding for file operations.
  • Create save files with restrictive permissions where the operating system supports doing so.
  • Avoid overwriting existing files unintentionally; use exclusive creation or atomic replacement where appropriate.

Example hardened implementation:

python
import json
import re
from pathlib import Path

SLOT_PATTERN = re.compile(r"^[A-Za-z0-9_-]{1,64}$")

def get_save_file(slot="auto"):
    if not isinstance(slot, str) or not SLOT_PATTERN.fullmatch(slot):
        raise ValueError("Invalid save-slot identifier")

    save_dir = Path("~/.text-game/saves").expanduser().resolve()
    save_dir.mkdir(parents=True, exist_ok=True)

    save_file = (save_dir / f"{slot}.json").resolve()
    if not save_file.is_relative_to(save_dir):
        raise ValueError("Save path escapes the save directory")

    return save_file

def save_game(game_state, slot="auto"):
    save_file = get_save_file(slot)
    save_file.write_text(
        json.dumps(game_state, ensure_ascii=False, indent=2),
        encoding="utf-8",
    )

def load_game(slot="auto"):
    save_file = get_save_file(slot)
    if save_file.is_file():
        return json.loads(save_file.read_text(encoding="utf-8"))
    return None
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (8)

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill repeatedly claims the free edition is local-only and does not require networking, yet its dependency section says an LLM API service is required. This mismatch can mislead users and host agents about privacy, data flow, and deployment assumptions, causing prompts or user content to be sent to external services when users reasonably expect purely local processing.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The keyword set is overly broad and includes generic terms like automation, tool, health, ecommerce, self, and text that are unrelated or only loosely related to a text-game skill. Such broad matching can cause unintended invocation across normal conversations, which is more dangerous here because the skill also declares file-reading and execution-related tools.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill requests generic 'exec' capability even though a text-game generation/playback workflow can be implemented with safer primitives or no code execution at all. In an agent environment, broad execution permission materially increases the attack surface because prompt-controlled content may be transformed into shell or interpreter actions, enabling arbitrary local command execution, file modification, or data exposure.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The capability matrix says the free edition does not support AI plot generation, but other sections instruct the agent to generate custom games from user prompts using LLM processing. This inconsistency is not code execution by itself, but it is a security-relevant integrity issue because users and platforms cannot accurately determine what automated generation behaviors the skill will perform.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill documents save/export behavior and later provides code that writes game state to ~/.text-game/saves, but it does not clearly warn users that local files will be created and retained. This creates a transparency and consent issue: user prompts, story content, and potentially sensitive text may be persisted on disk without an upfront disclosure.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger section is malformed and does not define specific activation cues or scope boundaries. In agent routing systems, broad or ambiguous triggers can cause the skill to activate on unrelated requests, increasing the chance that unnecessary tools or side effects such as file writes are used in the wrong context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

文档中的配置示例将 language 固定为 zh,且环境变量示例将 TEXT_GAME_LANGUAGE 设为 zh,同时功能表注明免费版“不支持多语言”。这会形成默认且单一的语言约束,但文档未提供用户选择、opt-in 机制,亦未说明这是特定区域限定工具。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

displayName 和 summary 完全使用中文,而文档面向“任意 AI Agent”平台用户,未在开头声明该技能仅面向中文用户或提供其他语言选项。结合后文免费版不支持多语言,整体上表现为未显式告知的语言限定。

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.