Back to skill

Security audit

Word Jumble

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent word-puzzle generator, with some renderer hardening issues but no evidence of hidden persistence, exfiltration, or purpose-mismatched authority.

Safe to install for generating your own puzzles. Do not use it to render puzzle JSON or image filenames from untrusted sources until the HTML escaping and validator checks are fixed, and remember that image prompts are sent to the configured external image generation provider.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/render_puzzle.py:42
Finding

Arbitrary HTML and JavaScript Injection During Puzzle Rendering

Content
View full analysis
str: with open(template_path) as f: html = f.read() html = html.replace("__PUZZLE_JSON__", json.dumps(puzzle)) html = html.replace("__CARTOON_IMAGE__", cartoon_filename) return html ``` `assets/puzzle-template.html:145-151`: ```html
Puzzle hint illustration
` can terminate the surrounding script because HTML parsing recognizes the closing tag even when it appears inside a JavaScript string. The remainder of the value can then introduce a new script or arbitrary HTML. Likewise, `os.path.basename()` used by the caller removes directory components but does not remove quotation marks or HTML metacharacters. A crafted image filename can close the `src` attribute and inject additional attributes or elements. The application subsequently serves the generated file over localhost and directs a browser to load it. Therefore, injected active content executes in the rendering browser's security ...[truncated 2094 chars]
Remediation
View remediation
response.json()); ``` 2. If inline JSON is required, place it in a non-executable element: ```html ``` Before insertion, escape characters significant to HTML parsing, including at minimum: - `<` as `\u003c` - `>` as `\u003e` - `&` as `\u0026` - U+2028 and U+2029 where relevant Parse the element's text as JSON rather than evaluating it as JavaScript. 3. Do not interpolate the image filename into markup. Create the image element with a fixed template and assign the filename through a DOM property after validating it, or apply context-specific HTML attribute escaping. 4. Restrict accepted image filenames to a conservative allowlist, such as: ```text ^[A-Za-z0-9._-]+$ ``` Reject quotes, angle brackets, control characters, URL schemes, and path separators. 5. Add a restrictive Content Security Policy that blocks inline and remote scripts. For example, move legitimate JavaScript to a static file and use: ```text Content-Security-Policy: default-src 'none'; script-src 'self'; img-src 'self'; style-src 'self' ``` This should be treated as defense in depth rather than a substitute for correct encoding. 6. Add regression tests using clue values containing ``, quotes, angle brackets, ampersands, and Unicode separators, as well as image filenames containing quotes and markup. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/validate_puzzle.py:25
Finding

Invalid Circled Positions Can Bypass Validation or Crash the Validator

Content
View full analysis
Remediation
View remediation
len(unscrambled) ] if invalid_positions: errors.append( f"{tag}: invalid circled positions {invalid_positions}; " f"positions must be integers from 1 to {len(unscrambled)}" ) extracted = [] else: extracted = [unscrambled[pos - 1] for pos in circled] ``` Additional hardening should include: 1. Validate that `scrambled`, `unscrambled`, `circled`, `clue_letters`, and `solution` have the expected list types. 2. Validate that letter arrays contain strings of the expected length. 3. Decide whether duplicate circled positions are valid; reject them if each position is intended to be unique. 4. Report oversized positions explicitly rather than silently omitting them. 5. Catch malformed top-level JSON structures and return controlled validation errors. 6. Add tests for zero, negative, oversized, boolean, floating-point, string, duplicate, and empty position values. ]]>
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 (4)

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 3)May include surrounding context.

md
---
name: word-jumble
description: Generate a Word Jumble puzzle — scrambled words with circled letters that spell out a final idiom, plus a cartoon illustration hint and a printable puzzle image. Use when asked to generate a word jumble, create a daily puzzle, or schedule a jumble. Output is a puzzle JSON file, a cartoon image, and a printable 900×900px screenshot — posting/scheduling is the caller's responsibility. Note: uses the platform image_generate tool to create cartoon illustrations, which sends prompts to an external image generation API (whichever provider is configured).
---

# Word Jumble

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 3)May include surrounding context.

md
---
name: word-jumble
description: Generate a Word Jumble puzzle — scrambled words with circled letters that spell out a final idiom, plus a cartoon illustration hint and a printable puzzle image. Use when asked to generate a word jumble, create a daily puzzle, or schedule a jumble. Output is a puzzle JSON file, a cartoon image, and a printable 900x900px screenshot — posting/scheduling is the caller's responsibility. Note: uses the platform image_generate tool to create cartoon illustrations, which sends prompts to an external image generation API (whichever provider is configured).
---

# Word Jumble

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code contradicts its own comment: instead of ROT13-encoding or otherwise hiding the answer, it appends the plaintext solution directly into the DOM via textContent. In a puzzle skill, this defeats the integrity of the game and allows any user or embedding page with DOM access to trivially read the answer, making answer disclosure immediate rather than requiring puzzle solving.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document sets lang="en", which hard-codes English as the page language. Under the policy, forcing a specific language or locale without user opt-in or clear justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.