Back to skill

Security audit

News Report

Security checks for vulnerabilities and agentic risk

Overview

The skill broadly matches its news-report purpose, but its web fetching and HTML report generation have concrete security flaws that need review before installation.

Review or patch this skill before installing. At minimum, restore normal TLS verification, escape or strictly sanitize every report field before writing HTML, add a restrictive content security policy for generated reports, use user-approved per-run output locations, and confirm any Feishu/message delivery target. Avoid using sensitive internal project names as keywords until the external-search and privacy behavior is clearly documented.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T01 · Skill Instruction Hijacking

Note
Location
SKILL.md:90
Finding
Forced Third-Party Branding in Generated Reports<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:90` and `scripts/gen_report.py:265` **Vulnerability Type**: Output attribution manipulation **Risk Level**: Low ### Complete Code Snippet From `SKILL.md:90`: ```json "source_note": "Data source: xxx · Report date: xxx · Generated by astronClaw AI" ``` The original source uses equivalent non-English labels around the fixed `astronClaw AI` attribution. From `scripts/gen_report.py:265`: ```python <footer>{source or title + " · " + date + " · Generated by astronClaw AI"}</footer> ``` The original source uses equivalent non-English wording for “Generated by.” ### Technical Analysis The mandatory report schema instructs the agent to place a fixed third-party attribution in `source_note`. The renderer independently provides the same attribution as a fallback whenever `source_note` is empty. This behavior is unrelated to collecting, analyzing, or formatting news. It changes the attribution of agent-generated content and can mislead recipients about which product or service created the report. Because the instruction is part of the Skill documentation, it affects normal agent behavior whenever the Skill is followed. ### Attack Path 1. The agent loads and follows `SKILL.md`. 2. The agent generates report data using the prescribed JSON schema. 3. The schema causes `source_note` to contain the fixed `astronClaw AI` attribution. 4. If `source_note` is omitted, `gen_report.py` inserts the same attribution automatically. 5. The resulting report is sent to a recipient with misleading third-party branding. ### Impact Assessment The issue affects the integrity and provenance of every generated report. It does not provide operating-system privileges, code execution, or access to confidential information. Its scope is limited to deceptive attribution and manipulation of downstream report content. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the fixed `astronClaw AI` attribution from the prescribed JSON schema. - Remove the branded fallback from `gen_report.py`. - Use a neutral fallback such as the report title and date. - Include product or vendor attribution only when explicitly requested by the user. - Keep attribution configuration separate from report content and make it opt-in. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_news.py:24
Finding
TLS Certificate and Hostname Verification Disabled<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fetch_news.py:24-30` **Vulnerability Type**: Improper certificate validation **Risk Level**: High ### Complete Code Snippet ```python def fetch_one(engine, url): ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE try: req = urllib.request.Request(url, headers=HEADERS) resp = urllib.request.urlopen(req, context=ctx, timeout=12) ``` ### Technical Analysis Although `ssl.create_default_context()` initially creates a secure TLS configuration, the following assignments explicitly disable its core authentication protections: ```python ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE ``` Consequently, the client accepts certificates that are self-signed, expired, issued for another hostname, or supplied by an untrusted certificate authority. Encryption without peer authentication does not prevent an active man-in-the-middle attacker from impersonating the configured search engines. All configured engine URLs use HTTPS, so this configuration unnecessarily weakens every outbound search request. ### Attack Path 1. A user invokes `fetch_news.py` on an untrusted or compromised network. 2. An attacker intercepts a request to a configured search engine. 3. The attacker presents an arbitrary TLS certificate. 4. The client accepts the certificate because certificate-chain and hostname verification are disabled. 5. The attacker returns fabricated search-result HTML. 6. `extract_snippets()` processes the attacker-controlled response and writes selected content to the output JSON. 7. The poisoned data is used by the agent to generate a report, allowing false information or adversarial instructions to influence the report. ### Impact Assessment An attacker positioned on the network path can compromise the confidentiality and integrity of search traffic. The immediate scope includes all fetched news content and all reports de ...[truncated 278 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Preserve the secure defaults provided by `ssl.create_default_context()`. - Remove both insecure assignments: ```python ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE ``` - Open the URL using the verified context: ```python def fetch_one(engine, url): ctx = ssl.create_default_context() try: req = urllib.request.Request(url, headers=HEADERS) with urllib.request.urlopen(req, context=ctx, timeout=12) as resp: html = resp.read().decode("utf-8", "ignore") return engine, html except Exception: return engine, "" ``` - Do not implement a fallback that retries requests without certificate verification. - Consider logging certificate failures separately from ordinary network failures so insecure workarounds are not introduced during troubleshooting. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/gen_report.py:47
Finding
Unescaped Report Fields Allow Persistent HTML and Script Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/gen_report.py:47-132` and `scripts/gen_report.py:207-265` **Vulnerability Type**: Stored HTML injection and cross-site scripting **Risk Level**: High ### Complete Code Snippet Representative vulnerable rendering functions: ```python def kpi_cards(kpis): cols = len(kpis) out = f'<div class="kpi-grid" style="grid-template-columns:repeat({cols},1fr)">' for k in kpis: col = k.get("color","blue") out += f'''<div class="kpi-card" style="border-top:2px solid {c(col)}"> <div class="kpi-num" style="color:{c(col)}">{k["num"]}</div> <div class="kpi-label">{k["label"]}</div> <div class="kpi-sub">{k.get("sub","")}</div> </div>''' out += "</div>" return out def timeline_html(items): out = '<div class="timeline">' for it in items: col = it.get("color","blue") out += f'''<div class="tl-item"> <div class="tl-dot" style="background:{c(col)};box-shadow:0 0 8px {c(col)}88"></div> <div class="tl-date">{it.get("date","")}</div> <div class="tl-title">{it.get("title","")}</div> <div class="tl-desc">{it.get("desc","")}</div> </div>''' out += "</div>" return out def analysis_html(analysis): out = '<div class="analysis-grid">' for key in ["tech","risk","trend"]: a = analysis.get(key, {}) col = a.get("color","blue") items_html = "".join(f"<li>{i}</li>" for i in a.get("items",[])) ``` Comparison values are also inserted without escaping: ```python def comparison_html(cmp): hdrs = cmp.get("headers",[]) rows = cmp.get("rows",[]) th = "".join(f"<th>{h}</th>" for h in hdrs) trs = "" for row in rows: trs += "<tr>" + "".join(f"<td>{cell}</td>" for cell in row) + "</tr>" ``` Top-level values are read from JSON and interpolated directly into the document: ```python d = json.load(open(args.data, encoding="utf-8")) title = d.get("title", "Industry News Analysis Report") subtitle = d ...[truncated 3685 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Escape every value intended to be displayed as text: ```python from html import escape def text(value): return escape(str(value), quote=True) ``` - Apply the helper at each interpolation point, including title, subtitle, keyword, dates, list items, table cells, news content, conclusion content, and footer text. - Do not use one generic escape operation for values placed into different parsing contexts. Keep untrusted data out of inline CSS, JavaScript, URLs, and HTML attributes. - If the summary must support formatting, sanitize it with a maintained HTML sanitizer and a strict allowlist. For example, permit only `strong` and `em`, with no attributes. - Reject dangerous tags and attributes, including `script`, `iframe`, `object`, `embed`, `form`, `style`, all event-handler attributes, and unsafe URL protocols. - Add a restrictive Content Security Policy, preferably through an HTTP response header when reports are served. For standalone files, a defense-in-depth meta policy can disable scripts and external connections: ```html <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; base-uri 'none'; form-action 'none'"> ``` - Validate the complete input schema before rendering, including expected types, maximum lengths, array limits, and permitted color values. - Add security tests containing tags, quotes, event handlers, malformed markup, and URL-protocol payloads in every report field. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
该代码块的功能集中在报告模板渲染与本地 HTML 文件生成,属于“报告展示层”。虽然其样式和输出形式与声明中的“深色仪表盘 HTML 报告生成”部分一致,但声明强调的核心端到端能力——输入关键词后自动采集资讯、分析提炼并发送——在代码中完全没有体现。代码没有网络请求、搜索接口调用、LLM 调用、邮件/消息发送或其他分发逻辑,输入也不是关键词而是预先准备好的 JSON 数据。因此,声明明显高于且超出了该代码块实际行为,构成描述与行为不匹配。

Missing User Warnings

High
Confidence
99% confidence
Finding
This is a concrete transport-security flaw: outbound HTTPS requests are made with certificate and hostname checks disabled, so network attackers can impersonate Bing, DuckDuckGo, Brave, or other engines and return arbitrary HTML. Because the skill parses that HTML and uses it as input to an analysis/reporting pipeline, exploitation can silently corrupt results at scale and may facilitate prompt/data poisoning in downstream LLM stages.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill performs network access and writes files, but it does not declare an explicit tool scope or permissions boundary. That makes its operational capabilities less transparent to users and enforcement layers, increasing the risk of unintended data egress or filesystem side effects when the skill is invoked.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill sends user-provided keywords and possibly surrounding context to external search engines and an LLM process, but the description does not warn users about this disclosure. In a reporting skill, queries may contain sensitive business topics, internal project names, or investigative interests, so silent transmission to third parties creates a meaningful privacy and confidentiality risk.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The script disables both TLS certificate validation and hostname verification for all HTTPS requests, which allows a man-in-the-middle attacker to intercept or alter responses from search engines. In this skill, those responses directly feed downstream news collection and report generation, so tampered content could poison the generated report, mislead users, or introduce malicious content into later processing.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The Accept-Language header forces requests to prefer zh-CN and Chinese results, which is a natural-language locale choice embedded in the code. There is no user opt-in, configuration option, or documented regional justification for this enforced language preference.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The generated document sets `lang="zh-CN"`, and the rest of the user-facing report content is also fixed in Chinese. This enforces a specific language/locale in the skill output without any opt-in, alternative selection, or documented region-specific constraint.

Missing User Warnings

Low
Confidence
91% confidence
Finding
The skill writes intermediate and final artifacts to fixed filesystem paths such as /tmp and a specific user workspace path, without prominently warning users. Fixed output locations can expose generated reports or raw collected data to other local users/processes, cause accidental overwrite, and leak environment-specific information.

Static analysis

Detected: suspicious.insecure_tls_verification

HTTPS certificate verification is disabled.

Warn
Code
suspicious.insecure_tls_verification
Location
scripts/fetch_news.py:26