T09 · Insecure Skill Coding Practices
- Location
lib/render.py:96- Finding
Unsanitized Book Title Permits Report Writes Outside the Intended Directory
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly does what it says, but it needs Review because crafted book titles can make it write report files outside its reports folder.
Review before installing. Use this only for explicit book-report requests, prefer an isolated virtual environment, avoid private PDFs unless you are comfortable with their contents being processed and persisted in reports, and patch the report filename handling to use sanitized titles with directory-containment checks.
lib/render.py:96Unsanitized Book Title Permits Report Writes Outside the Intended Directory
book-report/README.md:40Unpinned Global Installation of Third-Party Python Dependencies
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
elif "zhihu.com" in url:
headers["Referer"] = "https://www.zhihu.com/"
r = requests.get(url, headers=headers, timeout=TIMEOUT,
proxies=PROXIES if USE_PROXY else None)
r.raise_for_status()
r.encoding = r.apparent_encoding or "utf-8"
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
elif "zhihu.com" in url:
headers["Referer"] = "https://www.zhihu.com/"
r = requests.get(url, headers=headers, timeout=TIMEOUT,
proxies=PROXIES if USE_PROXY else None)
r.raise_for_status()
r.encoding = r.apparent_encoding or "utf-8"
The trigger words are extremely broad (e.g. "了解/研究/讲一下/聊/书/读") and can match ordinary conversation unrelated to requesting this skill. That increases the chance of unintended auto-invocation, causing unexpected web fetching, content generation, and local file creation without clear user intent.
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).
rm reports/*.html reports/*.md
不放心的话加 -i 逐个确认。
Code contains obfuscation (base64, hex encoding with execution). This is often used to hide malicious functionality.
<script type="text/javascript">
window.awsWafCookieDomainList = [];
window.gokuProps = {
"key":"AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AFPL1G3oJcTFBhlx+6LwB30AAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMP1vzbmgXNG41AiMOAgEQgDtC30jfk1Uc3Cb+uYKuU7yb30Xzzha7jVC2wcUOKEE6UAFYO855l7m1kCCrRQk87/36K4+U0OGyMUlY3Q==",
"iv":"grC9LAA/UQAAADdn",
"context":"UUnKZqTYrFcZOPCaJm84ycLOZf9iVLaS5WUnS98/H6ymuVDIzgzx2z9PwwALmTsc1fDrVyEN/4dmU3YYpL6QLt2h6VcDSO/Wvig4/g4DIiLYJsYhWAbwfIVECA6OiK2lartgwgS27NIagXi8j3TupelTbkGsM4ZFjnZyijJDappXuRU1uXMi3TD4wW4xud3RkpcB+Wdq4F6dd4A5oOvFvuZeVpyFxMcWajGkT79AVFlqjau/Ps3chlUMMJKKqGa3zDRdTlXUyYHQB9seGU4TUwcG3Cj6pod/CyaqM7vObu0QiTIckdJEvRIrT+icZeWv+0qYStqie/kXtcrG4lD/5P0oUwutuMB3ObBV2dtCqjUqqXt0wprLOPJCyk5cF1CdM0TFBCI="
};
Code contains obfuscation (base64, hex encoding with execution). This is often used to hide malicious functionality.
window.gokuProps = {
"key":"AQIDAHjcYu/GjX+QlghicBgQ/7bFaQZ+m5FKCMDnO+vTbNg96AFPL1G3oJcTFBhlx+6LwB30AAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMP1vzbmgXNG41AiMOAgEQgDtC30jfk1Uc3Cb+uYKuU7yb30Xzzha7jVC2wcUOKEE6UAFYO855l7m1kCCrRQk87/36K4+U0OGyMUlY3Q==",
"iv":"grC9LAA/UQAAADdn",
"context":"UUnKZqTYrFcZOPCaJm84ycLOZf9iVLaS5WUnS98/H6ymuVDIzgzx2z9PwwALmTsc1fDrVyEN/4dmU3YYpL6QLt2h6VcDSO/Wvig4/g4DIiLYJsYhWAbwfIVECA6OiK2lartgwgS27NIagXi8j3TupelTbkGsM4ZFjnZyijJDappXuRU1uXMi3TD4wW4xud3RkpcB+Wdq4F6dd4A5oOvFvuZeVpyFxMcWajGkT79AVFlqjau/Ps3chlUMMJKKqGa3zDRdTlXUyYHQB9seGU4TUwcG3Cj6pod/CyaqM7vObu0QiTIckdJEvRIrT+icZeWv+0qYStqie/kXtcrG4lD/5P0oUwutuMB3ObBV2dtCqjUqqXt0wprLOPJCyk5cF1CdM0TFBCI="
};
</script>
<script src="https://ea457862827c.c7756a6c.ap-northeast-1.token.awswaf.com/ea457862827c/ca63136f72fb/b63fc4339d15/challenge.js"></script>
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
<li><i><a href="/wiki/Angel_Down_(novel)" title="Angel Down (novel)">Angel Down</a></i> by <a href="/wiki/Daniel_Kraus_(author)" title="Daniel Kraus (author)">Daniel Kraus</a> (2026)</li></ul>
</div></td></tr></tbody></table></div>
<div class="navbox-styles"><link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1333133064" /><link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1353707246" /></div><div role="navigation" class="navbox authority-control" aria-labelledby="Authority_control_databases_frameless&#124;text-top&#124;10px&#124;alt=Edit_this_at_Wikidata&#124;link=https&#58;//www.wikidata.org/wiki/Q26505#identifiers&#124;class=noprint&#124;Edit_this_at_Wikidata1853" style="padding:3px"><table class="nowraplinks hlist mw-collapsible autocollapse navbox-inner" style="border-spacing:0;background:transparent;color:inherit"><tbody><tr><th scope="col" class="navbox-title" colspan="2"><div id="Authority_control_databases_frameless&#124;text-top&#124;10px&#124;alt=Edit_this_at_Wikidata&#124;link=https&#58;//www.wikidata.org/wiki/Q26505#identifiers&#124;class=noprint&#124;Edit_this_at_Wikidata1853" style="font-size:114%;margin:0 4em"><a href="/wiki/Help:Authority_control" title="Help:Authority control">Authority control databases</a> <span class="mw-valign-text-top noprint" typeof="mw:File/Frameless"><a href="https://www.wikidata.org/wiki/Q26505#identifiers" title="Edit this at Wikidata"><img alt="Edit this at Wikidata" src="//upload.wikimedia.org/wikipedia/en/thumb/8/8a/OOjs_UI_icon_edit-ltr-progressive.svg/20px-OOjs_UI_icon_edit-ltr-progressive.svg.png" decoding="async" width="10" height="10" class="mw-file-element" data-file-width="20" data-file-height="20" /></a></span></div></th></tr><tr><th scope="row" class="navbox-group" style="width:1%">International</th><td class="navbox-list-with-group navbox-list n
...[truncated 26 chars]
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
Lua memory usage: 9552776/52428800 bytes
Number of Wikibase entities loaded: 1/500
-->
<!--
Transclusion expansion time report (%,ms,calls,template)
100.00% 729.094 1 -total
16.28% 118.708 1 Template:Infobox_book
The description states a workflow of fetching from Wikipedia, Baidu Baike, and Zhihu, but does not clearly warn users up front that the skill will contact external websites. Unexpected outbound requests may expose user interests or prompts through network activity and can violate user expectations in privacy-sensitive environments.
The skill is described entirely in Chinese and explicitly depends on Chinese sources such as 百度百科, 维基百科(zh), and 知乎, while also framing its usage around Chinese-language output. It does not offer a user opt-in for language/locale or explain that the limitation is an intentional region-specific constraint.
The skill writes artifacts to the local filesystem under reports/ but the user-facing description does not prominently disclose that side effect before activation. If invoked unintentionally, it can create persistent local files containing scraped or synthesized content, which may surprise users and create privacy, storage, or workspace-integrity concerns.
This file contains natural-language interface text exclusively in Chinese, including usage instructions, help output, and error guidance. Under the policy rule for language/locale constraints, forcing a specific language without user choice is a natural-language policy violation.
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.
pip3 install requests jinja2
# 3. 注册 skill 到 Hermes(如果用 Hermes)
mkdir -p ~/.hermes/skills/book-report
cp SKILL.md ~/.hermes/skills/book-report/
# 4. 跑(任选一种方式)
This markdown file contains a natural-language locale restriction: '当前是中文专用'. The policy allows locale constraints only when the skill offers user choice or the restriction is clearly justified as region-specific; here the README presents the limitation as a blanket constraint rather than an opt-in language selection.
The English mode section states "报告仍用中文样式输出(界面统一)", which imposes a specific language/locale choice even when the user requests an English-language workflow. This is a natural-language policy concern because it does not offer the user a language choice or explicit opt-in for Chinese output.
The skill describes extracting content from local PDFs and combining it with web-fetched data for LLM-based structuring, but it does not clearly disclose that local document contents may be transmitted to or processed by an LLM. This creates a privacy and data-handling risk, especially if users provide copyrighted, personal, or sensitive PDFs under the assumption the processing is purely local.
The trigger phrases are broad enough to match ordinary requests about learning or discussing a book, which can cause the skill to activate without clear user intent. In an agent setting, this increases the chance of unprompted web fetching, PDF processing, and report generation that the user did not explicitly ask for.
The request headers hard-code Accept-Language to prefer Chinese, and the module description emphasizes Chinese Wikipedia and Chinese sources by default. This imposes a locale/language preference at runtime rather than offering the user a clear opt-in choice for request language behavior.
The script sends user-supplied book titles to multiple third-party services as part of URL construction and search queries, which can disclose potentially sensitive reading interests or research topics without an explicit privacy warning. In this skill's context, network exfiltration is the core behavior, so the main risk is privacy leakage rather than technical compromise.
The module docstrings and all user-facing CLI messages are written only in Chinese, indicating the skill is designed around a single language/locale with no visible option for user choice. Under the stated policy, forcing a specific language without opt-in is a natural-language policy concern unless the locale restriction is explicitly justified.
The module documentation says step 2 is 'LLM(本进程内)结构化抽取 9 字段', implying an in-process LLM performs structured extraction. In the implementation, extract_fields merely combines existing values from sources and optional pdf_data, with no LLM invocation or model-based extraction anywhere in the file.
The script writes fetched web content and PDF-extracted content to local report files automatically, without explicit confirmation, minimization, or sensitivity checks. In this skill context, users may provide private PDFs or search targets, so silent persistence can expose personal, copyrighted, or confidential data to other local users, backups, sync agents, or later unintended disclosure.
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.
</p><p>Many critics have drawn parallels not only between Santiago and St. James, but between Santiago and <a href="/wiki/Jesus" title="Jesus">Jesus</a> himself, especially with regard to Christ's <a href="/wiki/Passion_of_Jesus" title="Passion of Jesus">Passion</a> and <a href="/wiki/Crucifixion_of_Jesus" title="Crucifixion of Jesus">crucifixion</a>. Melvin Backman outlines several, beginning with the Santiago's wish to "rest gently ... against the wood and think of nothing"; Sylvester, Grimes, and Hays also cite the preceding scene, in which Santiago is cut and bleeds from near the eye, as a <a href="/wiki/Stigmata" title="Stigmata">stigmatic</a> evocation of the wounds inflicted by the <a href="/wiki/Crown_of_thorns" title="Crown of thorns">crown of thorns</a>.<sup id="cite_ref-FOOTNOTEBackman1962142SylvesterGrimesHays201869_47-0" class="reference"><a href="#cite_note-FOOTNOTEBackman1962142SylvesterGrimesHays201869-47"><span class="cite-bracket">[</span>47<span class="cite-bracket">]</span></a></sup> An often-cited passage occurs when Santiago spots two sharks:<sup id="cite_ref-FOOTNOTEBackman1962143Oliver199957,_247Waldmeir1962144_48-0" class="reference"><a href="#cite_note-FOOTNOTEBackman1962143Oliver199957,_247Waldmeir1962144-48"><span class="cite-bracket">[</span>48<span class="cite-bracket">]</span></a></sup>
</p>
<style data-mw-deduplicate="TemplateStyles:r1244412712">.mw-parser-output .templatequote{overflow:hidden;margin:1em 0;padding:0 32px}.mw-parser-output .templatequotecite{line-height:1.5em;text-align:left;margin-top:0}@media(min-width:500px){.mw-parser-output .templatequotecite{padding-left:1.6em}}</style><blockquote class="templatequote"><p>"Ay," he said aloud. There is no translation for this word and perhaps it is just a noise such as a man might make, involuntarily, feeling the nail go through his hands and into the wood.</p></blockquote>
<p>This passage was characterized by Sylvester, Grimes, and Hays as "a c
...[truncated 26 chars]
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
<li><i><a href="/wiki/James_(novel)" title="James (novel)">James</a></i> by <a href="/wiki/Percival_Everett" title="Percival Everett">Percival Everett</a> (2025)</li>
<li><i><a href="/wiki/Angel_Down_(novel)" title="Angel Down (novel)">Angel Down</a></i> by <a href="/wiki/Daniel_Kraus_(author)" title="Daniel Kraus (author)">Daniel Kraus</a> (2026)</li></ul>
</div></td></tr></tbody></table></div>
<div class="navbox-styles"><link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1333133064" /><link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r1353707246" /></div><div role="navigation" class="navbox authority-control" aria-labelledby="Authority_control_databases_frameless&#124;text-top&#124;10px&#124;alt=Edit_this_at_Wikidata&#124;link=https&#58;//www.wikidata.org/wiki/Q26505#identifiers&#124;class=noprint&#124;Edit_this_at_Wikidata1853" style="padding:3px"><table class="nowraplinks hlist mw-collapsible autocollapse navbox-inner" style="border-spacing:0;background:transparent;color:inherit"><tbody><tr><th scope="col" class="navbox-title" colspan="2"><div id="Authority_control_databases_frameless&#124;text-top&#124;10px&#124;alt=Edit_this_at_Wikidata&#124;link=https&#58;//www.wikidata.org/wiki/Q26505#identifiers&#124;class=noprint&#124;Edit_this_at_Wikidata1853" style="font-size:114%;margin:0 4em"><a href="/wiki/Help:Authority_control" title="Help:Authority control">Authority control databases</a> <span class="mw-valign-text-top noprint" typeof="mw:File/Frameless"><a href="https://www.wikidata.org/wiki/Q26505#identifiers" title="Edit this at Wikidata"><img alt="Edit this at Wikidata" src="//upload.wikimedia.org/wikipedia/en/thumb/8/8a/OOjs_UI_icon_edit-ltr-progressive.svg/20px-OOjs_UI_icon_edit-ltr-progressive.svg.png" decoding="async" width="10" height="10" class="mw-file-element" data-file-width="20" data-fi
...[truncated 26 chars]
The HTTP headers hard-code Accept-Language: zh-CN,zh;q=0.9,en;q=0.8, which imposes a specific locale preference on all requests. This is a natural-language policy concern because the skill does not offer the user a language choice or document a justified region-specific requirement.
Detected: suspicious.dynamic_code_execution