Back to skill

Security audit

Yumfu

Security checks for vulnerabilities and agentic risk

Overview

YumFu is a coherent RPG skill, but it needs review because its optional scheduled agent jobs and storybook export can reach beyond the clearly safe scope.

Install only if you are comfortable with an RPG skill that writes local saves and logs, generates media through provider tools, can send generated files back to chat, and can create opt-in recurring OpenClaw cron jobs. Review or patch the cron argument validation and storybook path handling before enabling daily evolution or sharing generated storybooks.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/generate_storybook_v3.py:201
Finding

Arbitrary Local File Inclusion in Generated Storybooks

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_storybook_v3.py, lines 201–253
Vulnerability Type: Unrestricted local file read and inclusion
Risk Level: High

Vulnerable Code

python
def _resolve_image_path(self, image_ref: str) -> Optional[Path]:
    if not image_ref:
        return None
    ref_path = Path(image_ref)
    if ref_path.exists():
        return ref_path

    basename = ref_path.name
    search_roots = [
        Path.home() / ".openclaw/media/outbound/yumfu",
        Path.home() / ".openclaw/media/outbound",
        Path.home() / ".openclaw/media/tool-image-generation",
        Path.home() / "clawd/output",
    ]

    for root in search_roots:
        if not root.exists():
            continue
        exact = root / basename
        if exact.exists():
            return exact

    stem = Path(basename).stem.lower()
    stem_tokens = [tok for tok in stem.replace("_", "-").split("-") if tok]
    for root in search_roots:
        if not root.exists():
            continue
        for p in root.rglob("*"):
            if not p.is_file():
                continue
            p_name = p.name.lower()
            p_stem = p.stem.lower()
            if basename.lower() == p_name:
                return p
            if stem and (stem in p_stem or p_stem in stem):
                return p
            if stem_tokens and sum(1 for tok in stem_tokens if tok in p_stem) >= max(2, min(4, len(stem_tokens))):
                return p
    return None

def collect_images(self, events: List[Dict[str, Any]]) -> Dict[str, Path]:
    image_map: Dict[str, Path] = {}
    for event in events:
        img_ref = event.get("image") or event.get("filename")
        if not img_ref:
            continue
        img_path = self._resolve_image_path(str(img_ref))
        if img_path and img_path.exists():
            dest = self.images_dir / img_path.name
...[truncated 3265 chars]
Remediation
View remediation

Remediation Suggestions

  1. Define a minimal allowlist of directories from which storybook images may be loaded.
  2. Canonicalize both the candidate and allowed roots with Path.resolve(strict=True).
  3. Require the canonical candidate to satisfy candidate.is_relative_to(allowed_root) for at least one allowed root.
  4. Reject absolute paths supplied by session data unless they resolve inside an approved root.
  5. Reject symbolic links or verify their fully resolved targets before opening them.
  6. Validate that candidates are regular files and impose a conservative maximum file size.
  7. Verify image content with an image decoder such as Pillow rather than relying on file extensions or mimetypes.guess_type().
  8. Copy and encode only the validated canonical path.
  9. Treat session logs as untrusted input and validate image and filename fields when they are first written.
  10. Add tests covering absolute paths, ../ traversal, symlink escapes, non-image files, oversized files, and valid assets under every approved media root.

A secure path check should follow this pattern:

python
candidate = Path(image_ref).expanduser().resolve(strict=True)
allowed_roots = [root.resolve(strict=True) for root in APPROVED_MEDIA_ROOTS]

if not candidate.is_file():
    return None
if not any(candidate.is_relative_to(root) for root in allowed_roots):
    return None
if candidate.is_symlink():
    return None

T01 · Skill Instruction Hijacking

Error
Location
scripts/create_daily_evolution_cron.py:21
Finding

Persistent Cron-Agent Prompt and Command Injection Through Unvalidated Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/create_daily_evolution_cron.py, lines 21–79
Vulnerability Type: Prompt injection into a persistent scheduled agent task
Risk Level: High

Vulnerable Code

python
parser = argparse.ArgumentParser(description='Create a per-player YumFu daily evolution cron job')
parser.add_argument('--user-id', required=True)
parser.add_argument('--universe', required=True)
parser.add_argument('--target', required=True, help='Telegram/chat target id')
parser.add_argument('--channel', default='telegram')
parser.add_argument('--time', default='20:00', help='Local delivery time HH:MM')
parser.add_argument('--tz', default='America/Los_Angeles')
parser.add_argument('--agent', default='main')
args = parser.parse_args()

hh, mm = args.time.split(':', 1)
cron_expr = f'{int(mm)} {int(hh)} * * *'
name = f'YumFu Daily Evolution [{args.universe}:{args.user_id}]'

message = f'''Run YumFu daily evolution for one player in safe sidecar mode.

Player:
- user_id: {args.user_id}
- universe: {args.universe}
- channel: {args.channel}
- target: {args.target}

Steps:
1. Run: python3 {RUNNER} --user-id {args.user_id} --universe {args.universe}
2. Read the JSON payload and generate one concise daily evolution update in the player's preferred language.
3. Generate one image matching image_prompt.
4. Write the generated JSON result to ~/clawd/tmp/yumfu-daily-{args.universe}-{args.user_id}.json
5. Run execution helper:
   python3 ~/clawd/skills/yumfu/scripts/execute_daily_evolution_delivery.py --user-id {args.user_id} --universe {args.universe} --target {args.target} --json ~/clawd/tmp/yumfu-daily-{args.universe}-{args.user_id}.json
6. Follow the returned execution plan exactly:
   - send listed `sends` items in order
   - after each successful send, run the matching `mark_commands`
   - run `apply_command` after delivery steps complete
7. Persist sidecar only using the 
...[truncated 4541 chars]
Remediation
View remediation

Remediation Suggestions

  1. Validate user-id and chat targets against strict platform-specific formats, such as an allowlisted numeric pattern and bounded length.
  2. Validate universe against the exact set of installed world identifiers.
  3. Restrict channel, agent, and timezone values to explicit allowlists.
  4. Reject control characters, line breaks, null bytes, quotes, backticks, command separators, and unexpected whitespace in every identifier.
  5. Do not construct shell commands in natural-language prompts.
  6. Replace the agent-authored workflow with a fixed executable runner that receives a structured JSON configuration and invokes subprocesses with argument arrays.
  7. If an agent prompt remains necessary, store opaque identifiers in a validated JSON payload and instruct the agent to call one fixed helper without reconstructing commands.
  8. Avoid putting attacker-controlled values into cron job names or free-form task instructions.
  9. Apply least privilege to the cron agent: constrain filesystem roots, permitted tools, outbound destinations, and executable commands.
  10. Record the creator, validated destination, and consent state for every scheduled job and provide a clear revocation mechanism.
  11. Add tests using newline injection, prompt directives, shell metacharacters, path traversal, oversized identifiers, invalid timezones, and unexpected agent names.
  12. Review and remove already-created cron jobs containing values that do not conform to the new validation rules.

A safer architecture would register a fixed message containing only a generated job identifier. The runner would load a server-created configuration, validate it again, and perform delivery without allowing an LLM to reinterpret user-controlled command text.

Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (190)

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · SECURITY_ANALYSIS.md (reported line 195)May include surrounding context.

md
### Phase 1: Documentation (No code changes)
- [ ] Add SECURITY.md
- [ ] Update SKILL.md examples (remove `exec()` strings)
- [ ] Add security badges to README

### Phase 2: Code Hardening (Optional)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The supplied code does not implement a multiplayer RPG experience or any Telegram/group interaction. It is a backend state-persistence script that accepts CLI arguments and saves evolution/progression data to a local filesystem path under the user's home directory. While some fields relate to story progression (summary, story_text, image_prompt, routes, advancement), the chunk's actual purpose is narrow: recording daily evolution state and history for a user/universe. That is only a supporting storage component, not the declared end-user skill behavior. Because the description presents an interactive multiplayer RPG with AI art and group play, while this code only writes local state files, the declared purpose materially overstates and misrepresents what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents an end-user multiplayer RPG experience in Telegram, but the supplied code does not implement gameplay, messaging, AI art, world logic, or player interaction. Instead, it is an internal maintenance script for backing up local save files using Git. This is a materially different purpose and introduces undeclared filesystem and version-control behavior. While backup could be a supporting implementation detail for the broader product, this specific code chunk itself is not accurately represented by the declared skill description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The supplied code chunk does relate to the general RPG domain described, but its actual behavior is much narrower and materially different from the declared purpose. The description presents a multiplayer Telegram group RPG with 10 worlds, shared play, PvP, team quests, and AI art scenes. This code only implements an interactive character creation utility, apparently intended to run from the command line. It reads local world configuration files, asks the user for character details, constructs a portrait prompt, and writes the resulting character JSON to a local save directory. There is no evidence here of Telegram integration, multiplayer/group coordination, scene generation, natural-language gameplay, PvP, or quest handling. While character creation is a supporting part of such a game, the declared description does not accurately represent what this specific code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents an end-user multiplayer RPG experience in Telegram groups. The supplied code chunk does not implement gameplay, world logic, natural-language interaction, PvP, quests, or scene generation directly. Instead, it creates and registers a scheduled cron job, builds an automation message for a sidecar process, and updates stored daily-evolution settings for a player. While this may support the broader RPG product, the code's actual purpose in this chunk is backend scheduling/automation infrastructure, which is a materially different primary behavior from the declared gameplay-focused description. Therefore this chunk is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The supplied code chunk does not implement or directly support the declared primary user-facing purpose of a multiplayer text RPG. Instead, it performs language inference for a YumFu player using recent text and stored metadata. While this may be an internal support script for the broader RPG system, the code's actual behavior is materially different from the declared description: it analyzes Chinese/English language preference, accesses save and world metadata files, and emits a JSON report. None of the advertised gameplay features, worlds, Telegram interaction, scene generation, or adventure mechanics appear in this chunk. Therefore this description does not accurately represent what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents an end-user multiplayer RPG experience in Telegram. The supplied code does not implement gameplay, world interaction, AI art, group chat behavior, PvP, quests, or natural-language RPG logic. Instead, it is an operational utility script for disabling a daily evolution cron and updating related stored state for a user/universe. This is a materially different primary purpose and introduces undeclared administrative capabilities (cron/job control and sidecar state mutation), so the description does not accurately represent the code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents an end-user multiplayer RPG experience in Telegram groups. However, the supplied code does not implement gameplay, world interaction, AI art, PvP, team quests, or natural-language RPG behavior. Instead, it is an operational helper that calls another script to create a scheduled daily evolution cron job for a user/world. This is a materially different primary purpose and introduces undeclared automation/scheduling capability at the system level. While it may support the broader YumFu product, this specific code chunk is not accurately represented by the declared skill description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents an end-user multiplayer text RPG experience in Telegram groups, with multiple fictional worlds, player characters, PvP/team quests, and natural-language play. The supplied code does not implement gameplay or user interaction. Instead, it is an orchestration utility for a daily content delivery pipeline: it calls a preparation script, builds ordered send instructions for image/text/voice, generates post-send state-mark commands, and outputs a final apply command. While the code references story, image, voice, and Telegram as a channel, its primary purpose is operational delivery/state management rather than running a multiplayer RPG. This is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a multiplayer text RPG for Telegram groups with multiple worlds, character-based shared gameplay, PvP, quests, and AI art as part of the experience. The supplied code chunk does not implement game logic or Telegram integration. Its actual function is limited to generating or editing images from prompts and optional input images using the Gemini 3 Pro Image API, saving the result to disk, and optionally applying a YumFu logo overlay. While AI art is mentioned in the description, this code is only an image-generation helper and does not by itself realize the declared primary purpose. Therefore the code chunk materially differs from the declared skill behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is for an interactive multiplayer RPG experience on Telegram. The supplied code does not implement gameplay at all; instead, it is a legacy utility script for generating a local HTML storybook from existing save data and copied images. Its primary purpose is archival/export, not playing the game. It reads user save files and image metadata from local paths, writes files to a storybook directory, and optionally launches a browser—capabilities not reflected in the declared description. While it is related to the YumFu project domain, this code chunk materially differs from the declared skill purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents an interactive multiplayer Telegram RPG experience. The supplied code does not implement gameplay at all; instead, it is a deprecated storybook generator tool. It loads an existing user's saved game from local disk, parses notes into event types, copies previously generated image files, renders an HTML report/storybook, saves it locally, and attempts to open it in a browser. This is a materially different primary purpose from the declared skill. The code also uses local filesystem resources and CLI arguments rather than Telegram/group triggers. While the generated storybook relates to the YumFu game domain, this chunk's actual behavior is an auxiliary export utility, not the described multiplayer RPG skill.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The description presents an interactive multiplayer RPG skill for Telegram groups. The supplied code does not implement gameplay, messaging, group coordination, command handling, PvP, quests, or scene generation. Instead, it is a post-processing/export tool: it loads session JSONL logs and save data from local directories under the user's home folder, copies/resolves image files from several local media/output paths, renders an HTML 'storybook' with stats and scenes, writes it to disk, and opens it in a browser. This is a materially different primary purpose. Additionally, the code uses filesystem resources that are not reflected in the declared permissions, and its hardcoded world metadata covers only some of the worlds named in the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a full multiplayer text RPG experience in Telegram groups, emphasizing world selection, character play, PvP, quests, and AI-generated scene art. The supplied code chunk does not implement gameplay, Telegram group interaction, world logic, natural-language command handling, PvP, quests, or image generation. Instead, it is a narrow backend helper for generating turn narration audio via Edge TTS and persisting TTS preferences in save data. While TTS could be a supporting feature of the RPG, this chunk’s actual primary purpose is materially different from the declared end-user skill description and introduces undeclared capabilities around audio generation, save-state modification, filesystem writes, and subprocess execution.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents the skill as a multiplayer text RPG experience in Telegram groups. The supplied code chunk does not implement gameplay, world interaction, AI art, PvP, or natural-language adventure features. Instead, it specifically handles a user's choice about enabling or disabling daily automated world evolution, calling separate scripts to set up or remove scheduled behavior. While this may support the broader RPG product, it is a materially narrower and different function than the declared purpose, and it introduces automation/scheduling behavior not mentioned in the description. Therefore this code chunk does not accurately match the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The supplied code chunk does not implement the declared end-user RPG experience. Instead, it is a backend/helper script for reading local save data from ~/clawd/memory/yumfu/saves and reporting it as JSON or console output. While save loading is plausibly related to the broader RPG system, this specific chunk’s actual purpose is a storage inspection/load tool, not a multiplayer Telegram text adventure skill. The code accesses local filesystem save data and provides CLI flags for querying one world or all worlds, which are not reflected in the declared description. Therefore, the description does not accurately represent what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is for a full multiplayer text RPG experience in Telegram groups. The supplied code does not implement gameplay, player interactions, world logic, character management, or messaging triggers. Instead, it is a support script that orchestrates other scripts to build reentry context, render continuation text, and generate/reuse an image for delivery. While the references to YumFu and image generation are thematically related, the actual primary purpose is a backend content-preparation tool, which is materially different from the declared end-user RPG functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents an end-user multiplayer Telegram RPG experience. The supplied code chunk is instead an internal operational script for preparing outbound daily-evolution content. Its primary function is asset orchestration: loading payload files, detecting language, formatting recap/story text, checking prior delivery state, optionally generating/reusing an image, invoking TTS generation, and emitting JSON describing next delivery actions. While this may support the broader YumFu product, it does not itself implement the described RPG behavior, worlds, player interactions, or Telegram group gameplay. This is therefore a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents an interactive multiplayer text RPG experience in Telegram groups. The supplied code does not implement gameplay, multiplayer interaction, AI scene generation, PvP, quests, or natural-language game handling. Instead, it is a maintenance/utility script for post-run storybook preparation: it reads a saved game file, checks a tracking flag, calls a refresh_storybook script, and emits JSON metadata so another component can send an HTML storybook to chat. This is a materially different primary purpose from the declared skill behavior, so it should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents an end-user multiplayer Telegram RPG experience with multiple worlds, AI-scene art, PvP, and natural-language play. The supplied code does not implement gameplay or Telegram interaction. Instead, it is an internal utility script for regenerating a storybook HTML output by invoking another Python script, locating the latest output folder, creating/updating a symlink, and returning file paths in JSON. While this may support the broader RPG system, the code chunk’s actual purpose is materially narrower and operationally different from the declared skill behavior, so this is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a full multiplayer Telegram RPG experience with multiple worlds, shared persistent gameplay, and AI-generated scene art. The supplied code does not implement a game, multiplayer features, Telegram interaction, world logic, or art generation. Instead, it is a narrow helper script whose sole purpose is to convert raw player and AI turn text into cleaner storybook prose. While it references '/yumfu' in input normalization, that is only superficial formatting support and does not substantiate the broad declared functionality. This is a clear material mismatch in primary purpose and capabilities.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The supplied code does not implement or directly support the described multiplayer RPG gameplay experience, Telegram group interaction, AI art generation, PvP, quests, or natural-language play. Instead, it is an admin/utility script for repairing the language field in stored save files by reading world metadata and optionally writing corrected values back to disk. This is a materially different primary purpose and introduces filesystem read/write capabilities over saved user data that are not reflected in the declared description. While it may be related to the broader YumFu project, this specific code chunk is a maintenance tool, not the described skill behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents the skill as an end-user multiplayer text RPG experience in Telegram groups. The supplied code chunk does not implement or expose RPG gameplay features; instead, it is a support script for selecting and persisting TTS voices based on world and language. While TTS could be an internal supporting feature of the RPG system, this chunk’s actual purpose is specifically configuration resolution for speech output, which is materially different from the declared primary purpose. Therefore this code chunk does not accurately represent the stated description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description presents an end-user-facing multiplayer Telegram RPG experience. The supplied code chunk does not implement gameplay, Telegram group interaction, PvP, team quests, world selection UX, or AI art delivery to users. Instead, it is a backend CLI utility that prepares context for a daily evolution update and optionally applies generated results by calling other scripts and processing JSON. This is a materially different primary purpose from the declared description. While such a script could support the RPG system internally, the code chunk itself performs undeclared orchestration and persistence tasks rather than the described gameplay behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The code is related to the declared RPG skill, but the supplied chunk does not implement the advertised primary user-facing behavior of a multiplayer Telegram text RPG. Instead, it performs an offline/supporting function: generating per-user daily world-evolution narrative updates from local save data. That is a materially narrower and different behavior than the description, and it also involves undeclared local file access. While support code need not mirror the full product description exactly, this chunk lacks evidence of key declared capabilities such as multiplayer/group play, Telegram integration, PvP, team quests, or commandless interaction. Therefore the description does not accurately represent what this specific code chunk actually does.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.