T09 · Insecure Skill Coding Practices
- Location
scripts/scraper.py:183- Finding
Server-Side Request Forgery Through User-Controlled URLs
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a real novel-scraping skill, but it has review-worthy unsafe edges around arbitrary URL fetching and output file writing.
Review this skill before installing. It is not showing clear malicious intent, but only run it on URLs you trust, avoid internal/private network addresses, be cautious with --force-spa, and do not use --output values containing paths or traversal. Treat the cleanup commands as permanent deletion commands and consider pinning dependencies before installation.
scripts/scraper.py:183Server-Side Request Forgery Through User-Controlled URLs
scripts/merge_novels.py:139Arbitrary File Overwrite Through Output Path Traversal
requirements.txt:4Unpinned and Redundant Python Dependencies
The file claims network scraping, BeautifulSoup/curl usage, pagination handling, and TXT output workflows that static analysis indicates are not present. In a skill that already references shell commands and file paths, this discrepancy increases operational risk because users may run cleanup or data-handling commands under false assumptions about what the tool actually created or consumed.
The file claims network scraping, BeautifulSoup/curl usage, pagination handling, and TXT output workflows that static analysis indicates are not present. In a skill that already references shell commands and file paths, this discrepancy increases operational risk because users may run cleanup or data-handling commands under false assumptions about what the tool actually created or consumed.
The file claims network scraping, BeautifulSoup/curl usage, pagination handling, and TXT output workflows that static analysis indicates are not present. In a skill that already references shell commands and file paths, this discrepancy increases operational risk because users may run cleanup or data-handling commands under false assumptions about what the tool actually created or consumed.
The skill instructs users to delete a progress file directly with rm, which is a shell-side destructive action presented as routine troubleshooting. In context this is not inherently malicious, but it conditions unsafe manual filesystem mutation and could cause loss of recovery state or mistakes if users adapt the path incorrectly.
rm ~/.openclaw/workspace/skills/novel-scraper-pro/state/progress.json
python3 scripts/scraper.py --chapters "1-100" --book "书名"
Using rm -rf with a wildcard in documentation is risky because it normalizes a powerful destructive shell pattern that users may modify or execute in the wrong context. While the target is a cache directory, the combination of recursive force deletion and globbing raises the chance of accidental data loss if the path is empty, expanded unexpectedly, or edited incorrectly.
/tmp/novel_scraper_cache/
rm -rf /tmp/novel_scraper_cache/*
Using rm -rf with a wildcard in documentation is risky because it normalizes a powerful destructive shell pattern that users may modify or execute in the wrong context. While the target is a cache directory, the combination of recursive force deletion and globbing raises the chance of accidental data loss if the path is empty, expanded unexpectedly, or edited incorrectly.
/tmp/novel_scraper_cache/
rm -rf /tmp/novel_scraper_cache/*
The skill advertises and instructs use of capabilities that include network access, local file writes, file reads, and shell command execution, yet it declares no explicit tool scope or permissions boundary. This creates an authorization/expectation gap: a reviewer or runtime may underestimate what the skill can do, increasing the chance of unintended filesystem modification or external access.
The description promotes scraping and saving output files but does not clearly warn about external network access and local filesystem writes. For a skill that targets user-provided URLs and writes under user directories, missing warnings reduce user awareness of privacy, compliance, and overwrite risks.
The documentation includes deletion commands for state and cache without an explicit warning that they are destructive and should be reviewed before running. Even though the paths appear specific, copy-pasted shell cleanup commands can lead to accidental data loss, especially if variables, globs, or paths are modified.
The manifest describes a novel scraping tool that uses curl and BeautifulSoup for fetching and parsing, so network access itself is expected. However, spawning an external process via subprocess.run adds command-execution capability that is broader than necessary for the stated purpose of scraping chapters and saving TXT output.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"-A", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
url,
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=35)
return result.stdout if result.returncode == 0 else None
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"-A", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
url,
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=35)
return result.stdout if result.returncode == 0 else None
The manifest promises a full-featured novel scraper with automatic pagination handling, resume support, memory monitoring, chapter content downloading, and formatted TXT output. This file only retrieves one fixed book's catalog, analyzes chapter URL gaps, and saves catalog metadata as JSON plus a URL list text file, which does not match the claimed end-user behavior.
The module docstring is entirely in Chinese, and the command help strings throughout the file are also Chinese-only, which imposes a language choice on users without offering an alternative or opt-in. This matches the policy category for language or locale constraints expressed in natural-language content.
The module docstring states '分页检测(默认检测,补全需启用 --complete)', implying completion is opt-in. However, scrape_urls always collects incomplete_chapters and later automatically completes them, and no --complete argument exists in the CLI, so the documentation contradicts actual behavior.
This scraper expands its capability from passive HTTP fetching to driving an external browser tool against attacker-controlled URLs. In skill contexts, that increases attack surface because malicious pages can trigger browser-based requests, script execution, internal-network access, or other side effects through the external tool, even if the Python code itself avoids shell injection.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def fetch_with_browser(url):
"""使用浏览器工具获取页面(SPA 支持)"""
try:
result = subprocess.run(
["openclaw", "browser", "fetch", "--url", url, "--wait", "2000"],
capture_output=True,
text=True,
Automatically launching another Python script as recovery behavior introduces hidden execution flow that users may not expect from a scraper. In an agent-skill environment, chaining to adjacent scripts increases the blast radius if the helper script is modified, compromised, or behaves unsafely, and it creates additional code-execution capability beyond the declared core task.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
catalog_script = Path(__file__).parent / "fetch_catalog.py"
logger.info(f"📚 运行目录页脚本:{catalog_script}")
result = subprocess.run(
["python3", str(catalog_script)],
capture_output=True,
text=True,
This markdown file contains substantial user-facing natural language in Chinese across multiple entries, but it does not indicate that the language is optional or intentionally localized. Under the language/locale policy rule, forcing a specific language without user opt-in can be a policy concern.
This JSON configuration contains user-facing natural-language strings exclusively in Chinese, such as the site name and notes, with no indication that the skill offers locale selection or is intentionally limited to Chinese-speaking users. The policy calls for flagging language or locale constraints when they are imposed without user opt-in or explicit justification.
The dependency specifier uses a lower-bound only constraint, which allows installation of any newer release of beautifulsoup4, including versions with breaking changes or a compromised upstream release. While this file alone does not prove exploitation, unpinned dependencies weaken supply-chain integrity and reduce build reproducibility.
# Novel Scraper - Python Dependencies
# Install: pip3 install -r requirements.txt --user
beautifulsoup4>=4.12.0
bs4>=0.0.1
The bs4 package is also specified with only a minimum version, so installs may resolve to any later release without review. In a tool that scrapes untrusted websites, predictable and reviewed dependency versions are important because parser/library behavior changes or supply-chain compromise could affect runtime safety and reliability.
# Install: pip3 install -r requirements.txt --user
beautifulsoup4>=4.12.0
bs4>=0.0.1
This file contains natural-language usage instructions exclusively in Chinese, which can constitute a language/locale policy violation when a skill forces a specific language without user opt-in. No alternative language option or justification for the locale constraint is documented in the file.
The top-level documentation describes a general-purpose catalog mapping tool, suggesting comprehensive handling of chapter URLs. In practice, main() is specialized to book_id "4" and additionally generates an output restricted to chapters numbered 116 and above, which contradicts the broad wording of the documentation.
No suspicious patterns detected.