Back to skill

Security audit

context-game

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Chinese-language game skill, but its save-slot handling can write outside the intended save folder and should be reviewed before installation.

Review before installing if your agent has broad filesystem write access. The skill should ideally reject '.', '..', and symlinked save slots and enforce that every save, backup, archive, and world file remains inside its saves directory. Users should also expect Chinese-language gameplay and local persistent files under the skill directory.

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
scripts/save.py:185
Finding
Save Slot Path Traversal Allows Writes Outside the Save Directory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/save.py`, lines 185-211 **Vulnerability Type**: Path traversal and insufficient filesystem boundary validation **Risk Level**: Medium ### Vulnerable Code ```python def slot_dir(slot): if not slot or any(ch in slot for ch in '/\\:*?"<>|'): # Error reporting omitted; it does not impose additional path constraints. fail(..., 1) return os.path.join(SAVES_DIR, slot) def slot_paths(slot): d = slot_dir(slot) return { "dir": d, "state": os.path.join(d, "state.json"), "memory": os.path.join(d, "memory.md"), "rolls": os.path.join(d, "rolls.jsonl"), "world": os.path.join(d, "world.json"), "archives": os.path.join(d, "archives"), } def atomic_write(path, text): """Temporary file followed by an atomic replacement in the same directory.""" d = os.path.dirname(path) os.makedirs(d, exist_ok=True) fd, tmp = tempfile.mkstemp(dir=d, prefix=".tmp_", suffix=".json") try: with os.fdopen(fd, "w", encoding="utf-8", newline="\n") as f: f.write(text) os.replace(tmp, path) except BaseException: if os.path.exists(tmp): os.remove(tmp) raise ``` The resulting paths are used by commands including `init`, `update`, `world-init`, and `archive`. For example, `cmd_init()` writes to the paths without performing a containment check: ```python atomic_write(p["state"], json.dumps( ordered, ensure_ascii=False, separators=(",", ":") )) atomic_write(p["memory"], memory) os.makedirs(p["archives"], exist_ok=True) ``` ### Technical Analysis `slot_dir()` rejects conventional path separators and several platform-specific reserved characters, but it does not reject the special directory names `.` and `..`. It also does not canonicalize the resulting path or verify that the resolved path remains under `SAVES_DIR`. On POSIX systems, a slot value of `..` produces: ```text ...[truncated 2813 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Use a strict slot-name allowlist** Accept only a small, explicit character set and length: ```python import re SLOT_PATTERN = re.compile(r"^[A-Za-z0-9_-]{1,64}$") def validate_slot_name(slot): if not isinstance(slot, str) or not SLOT_PATTERN.fullmatch(slot): fail("Invalid slot name; use 1-64 letters, digits, underscores, or hyphens.", 1) if slot in {".", ".."}: fail("Reserved slot name.", 1) ``` 2. **Canonicalize and enforce containment** Resolve both the base directory and candidate directory, then compare them using `os.path.commonpath()`: ```python def slot_dir(slot): validate_slot_name(slot) base = os.path.realpath(SAVES_DIR) candidate = os.path.realpath(os.path.join(base, slot)) if os.path.commonpath([base, candidate]) != base: fail("Slot path escapes the save directory.", 1) return candidate ``` Do not use string-prefix checks because paths such as `/app/saves-evil` may share a textual prefix without being descendants. 3. **Reject symbolic-link slot directories** Before using an existing slot, inspect it with `os.lstat()` and reject symbolic links: ```python if os.path.lexists(candidate) and os.path.islink(candidate): fail("Symbolic-link save slots are not allowed.", 1) ``` 4. **Protect against time-of-check/time-of-use races** Where supported, use directory file descriptors and no-follow behavior such as `O_NOFOLLOW`. Perform file creation relative to an already-open trusted directory rather than repeatedly resolving path strings. 5. **Revalidate immediately before every write** Apply the same containment and symlink checks in `atomic_write()`, `backup()`, roll-log appends, archive creation, and other write paths. A single validation at argument parsing is insufficient if directories can change before the write. 6. **Add regression tests** Confirm that the ...[truncated 299 chars]
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (28)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description presents a conversational game engine, but the actual behavior includes backend state management, archive operations, world initialization, validation, and command execution against local files. This mismatch can mislead users and platform policy layers about what the skill is empowered to do, reducing informed consent and making risky capabilities appear as harmless gameplay. In security terms, capability understatement is dangerous because it hides side effects and trust boundaries.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The README documents a very broad activation phrase ("开始游戏") with no stated exclusions, namespace, or contextual guardrails. In an agent platform that uses description matching or phrase-based dispatch, this can cause unintended skill activation from ordinary conversation, enabling the game skill to take over the session and potentially invoke file/shell-capable behavior unexpectedly.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The migration notes explicitly state that the skill depends on broad description matching for "玩家说开始游戏即触发", again without defining boundaries or disambiguation. This increases the chance of accidental or adversarial prompt-based activation across platforms, especially where routing is fuzzy and the skill expects powerful tools like file I/O and shell execution.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill instructs the agent to read and write save files and invoke persistence-related commands, but it does not declare an explicit tool/permission scope. That creates an authorization ambiguity: a host may expose broader file capabilities than intended, and the skill text encourages filesystem access across multiple paths under the workspace. In a prompt-driven tool environment, undeclared file access is a real security and governance issue even if the apparent purpose is gameplay.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The manifest description and core instructions are written entirely in Chinese and frame the agent as a game engine for this experience, but they do not indicate that other languages are supported or that the user may opt into a different language. This creates a locale/language policy concern because the skill effectively imposes a single language without explicit user choice or justification.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The entire skill rules document is written in Chinese and does not indicate that users may choose another language or locale. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This markdown file contains user-facing skill instructions entirely in Chinese, and nowhere indicates that the user can choose another language or that the skill is intentionally limited to a Chinese-speaking context. Under the language/locale policy, forcing a specific language without opt-in is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The usage instructions explicitly tell the user to say “开始游戏” and describe the agent flow entirely in Chinese, with no indication that other languages are supported or that the user can choose a preferred language. This is a natural-language locale policy concern because the skill appears to prescribe a specific language without opt-in or documented justification.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The file is entirely authored in Chinese and provides no indication that language selection is user-driven or that alternative locales are available. In a general-purpose agent skill, this can override the user's preferred language, degrade comprehension of rules and safety-relevant state, and create prompt-routing or UX failures for users who do not read Chinese.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
This JSON skill content presents names, summaries, and faction notes exclusively in Chinese, which can amount to a language policy violation if the organization requires avoiding forced language selection without user opt-in. There is no visible indication in the file that the language is optional, selectable, or justified as a region-specific skill.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
This JSON file’s human-facing content is entirely in Chinese, including the skill name, descriptions, and opening situation text, with no indication that language is selectable or that the skill is intentionally restricted to a Chinese-speaking or China-specific deployment context. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This JSON file’s natural-language content consistently forces a specific language/locale experience through Chinese names, summaries, and scenario text. Under the policy, a language constraint should either be optional for the user or clearly documented as a justified region-specific requirement, which is not present here.

Natural-Language Policy Violations

Medium
Confidence
83% confidence
Finding
该行明确规定“展示名中文 2-4 字”,属于自然语言层面的语言约束。文档中未说明这是面向特定中文地区的受限场景,也未提供用户语言选择或 opt-in,因此可能违反语言/locale 选择政策。

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
This JSON world file presents all user-facing names, summaries, and gameplay instructions in Chinese, including core mechanics and opening situation text. Under the policy rule, forcing a specific language without opt-in can be a natural-language policy violation when no language choice or justification is provided.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The entire skill file is written in Chinese and does not offer any language choice, fallback, or opt-in mechanism. Under the policy for natural-language violations, forcing a specific language without user choice can be a locale-policy issue unless the regional constraint is explicitly documented and justified.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The natural-language content throughout the JSON is entirely in Chinese, including the skill/world names and descriptive text, with no indication that users may choose another language or that the locale restriction is intentional and justified. Under the stated policy, a skill that effectively requires a specific language without opt-in can be a language/locale policy violation.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The file’s user-facing natural-language content is entirely in Chinese, including names, summaries, notes, and opening situation text, with no indication that language selection is optional or that the skill is intentionally limited to a Chinese-speaking or region-specific context. This can violate organizational language/locale policy when a skill implicitly forces one language without user opt-in.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The skill content is entirely authored in Chinese, including all names, summaries, and relationship notes, with no indication that language choice is optional or user-selectable. Under the policy for natural-language violations, a skill that effectively constrains interaction to a specific language without opt-in should be flagged unless the locale restriction is explicitly documented and justified.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This JSON skill content is entirely written in Chinese, including the skill name, metadata notes, world descriptions, and opening situation, with no indication that users may choose another language or locale. That creates a natural-language locale constraint across the whole skill without documented opt-in or justification such as a region-specific compliance requirement.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This JSON defines core metadata entirely in Chinese, including the skill/world name, tone variant, calendar note, and current year, with no indication that other languages are supported or that Chinese is optional. Under the policy, forcing a specific language or locale without opt-in is a natural-language policy concern.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This JSON world definition is entirely written in Chinese, including names, summaries, and relationship notes, with no indication that the skill is region-specific or that users can opt into another language. Under the policy for natural-language violations, forcing a specific language without user opt-in is reportable across all file types.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
This JSON world file presents all user-facing names, summaries, and opening situation text exclusively in Chinese, with no indication that language is configurable or optional. Under the policy rule, a fixed language/locale without user opt-in is a natural-language policy violation unless clearly justified as region-specific, which is not documented here.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This JSON skill content uses Chinese throughout names, summaries, and notes, which effectively forces a specific language for users consuming the skill. The file does not indicate that Chinese is optional, user-selected, or required for a documented region-specific purpose.

Natural-Language Policy Violations

Medium
Confidence
83% confidence
Finding
Line L157 requires display names to use '玩家语言' ('the player's language'), which is a language/locale directive expressed in natural language. The file does not provide an explicit opt-in choice mechanism or a documented, justified locale constraint, so this can be read as forcing language behavior without user selection.

Natural-Language Policy Violations

Low
Confidence
74% confidence
Finding
Natural-language policy checks apply to all file types. The skill documentation presents the skill in a single fixed language without indicating that users may choose another language or that the locale restriction is intentional and justified, which can be a language-policy concern.

Static analysis

No suspicious patterns detected.