T09 · Insecure Skill Coding Practices
- Location
heatmap_template.html:60- Finding
Stored JavaScript Injection in Generated Heatmap Reports
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is purpose-aligned, but needs Review because its report generation can overwrite writable files, expose an AMap key, and allow script injection in generated HTML.
Install only if you trust the operator and can run it with limited filesystem permissions. Use a dedicated output directory, do not let untrusted users control output_dir or address strings, configure a separate browser-safe AMAP_JS_KEY, and rotate AMAP_KEY if it has already appeared in shared reports.
heatmap_template.html:60Stored JavaScript Injection in Generated Heatmap Reports
index.py:284User-Controlled File Placement and Overwrite
index.py:10Server-Side Amap Credential Exposed in Generated HTML
compare_template.html:7Runtime Execution of Third-Party CDN Script Without Integrity Verification
The skill declares access to environment variables, file writing, and network-backed behavior in its specification, but does not declare any explicit tool scope or permission boundaries. That makes it easier for an agent runtime to grant broader-than-necessary capabilities, increasing the risk of unintended outbound requests, secret exposure from env usage, or arbitrary file creation via generated HTML outputs.
The single-address trigger conditions are broad enough that ordinary conversational requests about opening a store or evaluating a location may auto-trigger this skill without strong confirmation. In a skill with network access and file generation, overbroad activation can cause unintended third-party API calls, unnecessary processing of user-supplied addresses, and creation of artifacts the user did not explicitly request.
The multi-address compare trigger is also loosely defined and could match general comparative questions, causing the skill to launch multiple parallel analyses. Because this mode amplifies network usage and data handling across 2-5 addresses, accidental triggering increases the blast radius through extra API consumption, potential leakage of location data to external services, and more generated output files.
The HTML declares lang="zh-CN" and all visible UI strings are fixed in Chinese, which imposes a specific language/locale on users. Under the policy, locale constraints should either be user-selectable or clearly documented as intentionally region-specific.
This code contains user-facing natural-language strings exclusively in Chinese, beginning with the startup error at L014 and continuing throughout summaries and validation messages. The file does not offer a language/locale option or document that the skill is intentionally limited to a Chinese-speaking or region-specific context, which creates a locale policy concern.
The skill writes persistent HTML reports to the filesystem even though the description emphasizes a simple one-sentence site-selection evaluation. Undisclosed file creation expands the skill's effective capability, may expose analyzed addresses and business intelligence on shared systems, and can surprise operators who did not expect persistent artifacts.
Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.
} for r in results],
table_data={k: v for k, v in table_data.items()},
amap_js_key=AMAP_JS_KEY,
timestamp=__import__("datetime").datetime.now().strftime("%Y-%m-%d %H:%M:%S")
)
os.makedirs(os.path.dirname(output_path), exist_ok=True)
The multi-address comparison path also generates and stores HTML reports, which is an additional persistence behavior not disclosed in the manifest. Because the report aggregates multiple candidate locations and rankings, the stored output could reveal more sensitive commercial planning data than a transient textual response.
The markdown explicitly states that the skill automatically generates interactive HTML heatmaps, and later examples show concrete file paths under /tmp where outputs are written. Because this behavior affects the local filesystem, the skill description should clearly disclose that files will be created and where they will be stored.
The document declares lang="zh-CN" and presents the UI text entirely in Simplified Chinese, which imposes a specific language/locale by default. Under the policy, locale constraints should either be user-selectable or clearly documented as justified for a region-specific tool.
The manifest frames the skill as a store site analysis tool, but does not disclose that it depends on reading secret credentials from process environment variables. While this may be an implementation detail, environment secret access is a capability that is not evident from the stated purpose alone.
The dependency specification uses a lower-bound version only (aiohttp>=3.9.0) rather than a pinned or tightly constrained version. This makes builds non-reproducible and can cause the environment to resolve to vulnerable or incompatible releases over time, especially for a network-facing HTTP library like aiohttp.
aiohttp>=3.9.0
jinja2>=3.1.0
Because aiohttp is not pinned, it is impossible to verify from this manifest whether the installed version avoids the listed advisories. In a skill that likely performs network requests to external APIs, uncertainty around the exact aiohttp version increases supply-chain and runtime risk, even if the manifest does not itself prove an exploitable CVE is present.
The dependency specification uses a lower-bound version only (jinja2>=3.1.0) instead of an exact pin or controlled range. This allows future installs to pull different versions, which undermines reproducibility and may introduce known-vulnerable releases or behavior changes into a templating component that is often security-sensitive.
aiohttp>=3.9.0
jinja2>=3.1.0
Because jinja2 is unpinned, the manifest does not establish whether deployment will use a version affected by any known Jinja2 advisories. Since templating libraries can become high-risk when used with untrusted input or sandbox assumptions, leaving the version unresolved creates unnecessary security ambiguity.
The skill description is written entirely in Chinese and presents the skill as Chinese-language oriented, but the manifest does not indicate that language selection is optional or that the skill is intentionally restricted to a Chinese-speaking context. Under the policy, locale or language constraints should either be opt-in or explicitly justified.