T09 · Insecure Skill Coding Practices
- Location
scripts/auto_screenshot.py:14- Finding
Shell Command Injection Through Attacker-Controlled HTML Path
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its image-generation purpose, but its screenshot and local-server helpers create command-execution and file-exposure risks that need review before installation.
Install only if you are comfortable running local Python scripts and browser automation from this package. Use it on trusted generated files, avoid passing arbitrary filenames to auto_screenshot.py, and do not run the server on untrusted networks unless it is changed to bind to 127.0.0.1 and serve only the intended output directory.
scripts/auto_screenshot.py:14Shell Command Injection Through Attacker-Controlled HTML Path
scripts/serve.py:15Unauthenticated HTTP Server Exposed on All Network Interfaces
If the underlying implementation runs a local HTTP server and serves files over localhost while claiming only to generate article images, the skill exposes undeclared network-facing behavior. Even on localhost, hidden server behavior expands attack surface, can expose local content, and undermines trust in the skill’s stated purpose.
If the underlying implementation runs a local HTTP server and serves files over localhost while claiming only to generate article images, the skill exposes undeclared network-facing behavior. Even on localhost, hidden server behavior expands attack surface, can expose local content, and undermines trust in the skill’s stated purpose.
The tool command parameter includes a file URL built from external input and is passed through a shell, allowing parameter or command manipulation. Because the skill's purpose is image creation, not arbitrary command execution, this mismatch makes the issue more dangerous: an attacker could turn a screenshot request into execution of unintended shell commands or malicious browser invocations.
# Open in browser
open_cmd = f'browser open --url "{file_url}"'
result = subprocess.run(open_cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
print(f"❌ Failed to open browser: {result.stderr}")
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
# Take screenshot
screenshot_cmd = f'browser screenshot --type png --fullPage'
result = subprocess.run(screenshot_cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
print(f"❌ Failed to take screenshot: {result.stderr}")
The skill advertises executable workflows that invoke Python scripts, write output files, and rely on browser automation, but it does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization and transparency gap: an agent may grant broader-than-expected shell and filesystem access when activating the skill, increasing the chance of unintended command execution or file modification.
The trigger phrases are broad enough to match ordinary image-related requests, which can cause the skill to activate unexpectedly. Over-broad activation is risky because it may invoke shell, file, or browser-capable workflows in contexts where the user only asked for general help, increasing the chance of unnecessary privileged actions.
The helper introduces shell command execution and browser automation capabilities that exceed simple image-generation logic and widen the attack surface. In the context of a skill meant to generate WeChat images, accepting local HTML and opening it in a browser can expose the environment to command injection, unsafe local-file rendering, or unintended access to local/browser resources.
This command is executed through the shell while embedding user-influenced data derived from html_path into the command string. Even though the path is wrapped in double quotes, shell metacharacters such as command substitution can still be interpreted, enabling command injection if an attacker controls the input path; this is especially risky in an automation helper that launches browser tooling.
# Open in browser
open_cmd = f'browser open --url "{file_url}"'
result = subprocess.run(open_cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
print(f"❌ Failed to open browser: {result.stderr}")
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
# Take screenshot
screenshot_cmd = f'browser screenshot --type png --fullPage'
result = subprocess.run(screenshot_cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
print(f"❌ Failed to take screenshot: {result.stderr}")
The skill documentation and usage guidance are primarily presented in Chinese, which can impose a language constraint on users without opt-in or an explicit note that the skill is intended for a Chinese-speaking audience. Under the language/locale policy, forcing a specific language without user choice or justification is a natural-language policy concern.
This markdown file instructs users to launch python3 -m http.server 8765 and open generated HTML in a browser, which affects local system behavior and can expose files in the output directory over the local network depending on environment configuration. The README presents this as a routine step but does not include any warning or disclosure about the server exposure or the fact that generated files will be served via HTTP.
The trigger list is entirely Chinese and the examples center on Chinese-language usage, but the description does not state that the skill is intentionally limited to Chinese-speaking or WeChat-specific users. That can amount to an implicit language/locale constraint without user opt-in or justification.
The document declares lang="zh-CN", which hard-codes Simplified Chinese as the page language. Under the policy, forcing a specific language or locale without offering user choice or documenting a justified region-specific constraint is a natural-language policy violation.
The document sets lang="zh-CN", which hard-codes a specific language/locale in the skill asset. Under the policy rules, locale-specific behavior should be optional or clearly justified, and this file provides neither a user opt-in nor a documented regional constraint.
The document declares lang="zh-CN", which hard-codes a specific language/locale. Under the policy criteria, forcing a locale without opt-in or documented justification is a natural-language policy concern.
The document sets the page language to "zh-CN", and the visible chart labels are also Chinese, which indicates a fixed language/locale choice. Under the policy, forcing a specific language without user opt-in or a documented justification is a natural-language policy concern.
The document sets lang="zh-CN", which hard-codes a specific language/locale. Under the policy criteria, forcing a locale without opt-in or clear justification can be a natural-language policy violation.
The document sets lang="zh-CN", which specifies a fixed language/locale for the skill output. Under the policy, locale constraints should either offer user opt-in or be clearly documented as necessary for a region-specific use case, neither of which is present in this file.
This is a manifest file, so vague-trigger review applies. The description says the skill can 'Generate beautiful images for WeChat articles' but provides no explicit trigger phrases, scope boundaries, or exclusion conditions, which could make invocation matching overly broad for generic image-generation requests.