T09 · Insecure Skill Coding Practices
- Location
scripts/publish_episode.py:56- Finding
Path Traversal and Arbitrary File Write During Episode Publishing
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill appears to be a legitimate Korean web-novel publishing helper, but its file-writing scripts are under-scoped and can write outside the intended draft or Quartz folders if given crafted inputs.
Install only if you trust the operator and will pass conservative, normal series and slug values. Before use, the publisher should add filename validation, containment checks under the configured draft and Quartz roots, and an explicit overwrite policy. The artifact does not show malicious exfiltration or persistence, but the filesystem write boundaries need review.
scripts/publish_episode.py:56Path Traversal and Arbitrary File Write During Episode Publishing
scripts/new_episode.py:19Path Traversal and Arbitrary File Overwrite During Draft Creation
The declared description presents a content-production and publishing pipeline for a Korean web-novel site. The supplied code instead implements a security/prepublish validation script that recursively scans repository files for private key signatures and suspicious strings such as webhook/pastebin references, curl/wget/powershell usage, and known threat markers. This is a materially different primary purpose from generating covers, converting media, producing episode markdown, linting, or publishing a Quartz-hosted serial. While a prepublish check could be a supporting detail in some workflows, the declared description does not mention any security-scanning capability, and this code chunk is specifically focused on that unrelated function.
The declared description presents a full web-novel production and publishing pipeline, including cover creation, image conversion, markdown generation, linting, and publishing, and explicitly mentions Nano Banana Pro and ffmpeg. This code chunk only acts as a post-review publishing wrapper: it validates arguments, derives Quartz paths, then runs publish_episode.py and sync_index.py. There is no evidence here of cover generation, WebP processing, draft creation, or use of Nano Banana Pro/ffmpeg. While publishing is part of the declared purpose, the actual code's primary function is narrower and includes a specific review-confirmation trigger not captured in the declaration. Therefore the description does not accurately represent this code chunk.
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).
#!/usr/bin/env python3
"""Pre-publish security check for ClawHub.
Scans for obvious private keys + common exfil/social-engineering markers.
Run from the skill folder:
python3 scripts/prepublish_check.py
SECURITY NOTE FOR ANTIVIRUS SCANNERS:
This file contains regex patterns to DETECT malicious code, not to EXECUTE it.
The patterns below are used to PREVENT malware from being published to ClawHub.
This is a security feature, similar to antivirus signature databases.
"""
from __future__ import annotations
import re
from pathlib import Path
SKILL_DIR = Path(__file__).resolve().parents[1]
# SECURITY NOTE: These patterns are used to DETECT threats, not create them.
# Similar to antivirus signature da
The skill advertises shell, file read, and file write behaviors but does not declare any explicit tool scope or permission boundaries. In an agent ecosystem, missing least-privilege declarations increases the chance that the skill can be invoked with broader-than-necessary capabilities, making unintended file modification or command execution more likely.
The description explicitly defines the skill as building and publishing a Korean web-novel serial, which sets a specific language/locale expectation. Because the file does not offer an alternate language option or explicit user opt-in for this constraint, it can violate the language/locale policy requirement.
The script requires a 'korean slug' and later generates fixed Korean body text and a 'lang-ko' tag, which enforces a specific language/locale in the output. This matches the policy concern for language constraints without user opt-in or documented justification.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def run_lint(lint_script: Path, file: Path) -> None:
proc = subprocess.run(["python3", str(lint_script), "--file", str(file)])
if proc.returncode != 0:
raise SystemExit(proc.returncode)
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
_, post = rest.split(END, 1)
new_text = pre + START + between + END + post
index_file.write_text(new_text, encoding="utf-8")
print(index_file)
No suspicious patterns detected.