Back to skill

Security audit

竞品前哨

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent competitor-monitoring tool, but its bundled HTML report automatically contacts third-party APIs and renders live external data unsafely, so users should review it before installing.

Review this before installing or sharing generated HTML reports. Disable the demo page's default live refresh, require explicit consent before contacting third-party sources, and sanitize/escape all external feed fields before rendering. Keep API keys in environment or secret storage as the skill instructs, and only enable cron, email, IM, or page publishing for clearly confirmed destinations.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
templates/report-demo.html:797
Finding

DOM-Based Cross-Site Scripting Through Untrusted External Feed Data

Content
View full analysis

Vulnerability Details

File Location: templates/report-demo.html, lines 797–846 and 1071–1097
Vulnerability Type: DOM-based cross-site scripting (DOM XSS)
Risk Level: Medium

Complete Code Snippet

javascript
function mapItem(s,it){
  return { c: s.comp||s.name, d:"自定义接入", pub: toISO(it.date), col: todayISO(),
    lv: s.lv, imp:"I2", review:(s.lv==="P2"||s.lv==="P3"), live:true, xval:false,
    ev: it.title, src: s.name, url: it.link||s.url||"#" };
}

function fetchSource(s){
  return new Promise((resolve,reject)=>{
    if(!s.url){ resolve([]); return; }
    const ctrl = ("AbortController" in window)? new AbortController() : null;
    const timer = setTimeout(()=>{ if(ctrl) ctrl.abort(); reject(new Error("超时(8s)")); }, 8000);
    fetch(s.url, ctrl ? {signal:ctrl.signal, mode:"cors"} : {mode:"cors"})
      .then(r=>{ if(!r.ok) throw new Error("HTTP "+r.status); return r.text(); })
      .then(text=>{
        clearTimeout(timer);
        let items=[];
        if(s.type==="RSS"){
          const doc=new DOMParser().parseFromString(text,"text/xml");
          const nodes=doc.querySelectorAll("item, entry");
          if(!nodes.length) throw new Error("RSS 无条目");
          nodes.forEach(n=>{
            const q=sel=>{ const e=n.querySelector(sel); return e?(e.textContent||e.getAttribute("href")||""):""; };
            items.push({ title:q("title"), link:q("link")||q("id"), date:q("pubDate")||q("updated")||q("published") });
          });
        } else {
          let json; try{ json=JSON.parse(text); }catch(e){ throw new Error("非 JSON(RSS 请选 RSS 类型)"); }
          let arr = s.path ? getPath(json,s.path) : (Array.isArray(json)?json:(json.items||json.data||json.results));
          if(!Array.isArray(arr)) throw new Error("未找到数组,检查列表路径");
          items = arr.slice(0,20).map(o=>({
            title:o.title||o.name||o.full_name||o.text||o.summary||String(JSON.stringify(o)).slice(0,60),
            link:o.html_url||o.url||o.link||o.homepage_url||
...[truncated 3946 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not render external text through innerHTML. Create elements with DOM APIs and assign all external strings through textContent.
  2. If rich formatting is required, sanitize it with a maintained HTML sanitizer configured with a strict allowlist of necessary tags and attributes.
  3. Parse every external link with new URL() and permit only explicitly supported schemes, normally https: and optionally http:. Reject javascript:, data:, file:, and malformed URLs.
  4. Apply contextual escaping separately for HTML text, attribute values, and URLs. A single generic replacement function is not sufficient for every context.
  5. Treat competitor names, source names, titles, summaries, and all fetched URL fields as untrusted, including values returned by built-in GitHub and Hacker News queries.
  6. Add a restrictive Content Security Policy that disallows inline script and limits network destinations. This should be defense in depth rather than a substitute for encoding.
  7. Add regression tests covering HTML event handlers, SVG payloads, quote-breaking attribute payloads, malformed URLs, and javascript: links.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (13)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 124)May include surrounding context.

md
- **HTML 可视化页**:套用 `templates/report-demo.html`(Notion 风、双轴彩色标签、发布/采集双日期、旧闻回收/交叉验证、竞品×维度矩阵、信源筛选、配置输入面板驱动整份报告实时重算、数据概览可视化含**可信度×影响度优先级象限**、术语解释折叠区)。用 Write 生成本地

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 227)May include surrounding context.

md
- **HTML 可视化页**:套用 `templates/report-demo.html`(Notion 风、双轴彩色标签、发布/采集双日期、旧闻回收/交叉验证、竞品×维度矩阵、信源筛选、配置输入面板驱动整份报告实时重算、数据概览可视化含**可信度×影响度优先级象限**、术语解释折叠区)。用 Write 生成本地

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The display name, category, and primary description are written in Chinese, and the usage examples and interaction flow assume Chinese user inputs such as replying with "对". The document does not state that users may choose another language or locale, so it effectively imposes a language preference without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This JSON schema contains natural-language descriptions and fixed enum values entirely in Chinese, which implicitly constrains generated or stored content to a specific language. The file does not indicate that this is an optional locale, user-selected preference, or a justified region-specific requirement, so it creates a language/locale policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The document declares zh-CN and all visible UI text is presented in Chinese, with no indication that users may choose another language. The policy requires flagging language or locale constraints when they are imposed without user opt-in or clear justification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The page claims to be a static demonstration with example data, but other code paths perform real-time external fetching and updates. This mismatch is dangerous because it defeats user expectations and informed consent, increasing the chance that users open the page in sensitive environments assuming no network activity will occur.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The page contains preconfigured external API endpoints and later fetches them client-side, causing outbound data transmission to third parties. In this skill's context, that is more sensitive because the page is for competitor intelligence workflows, so user selections and access patterns may reveal business interests even if only query terms are embedded in the URL.

Content

Scanner excerpt · templates/report-demo.html (reported line 1021)May include surrounding context.

html
{name:"HN·通义千问 Qwen", type:"API", url:"https://hn.algolia.com/api/v1/search_by_date?query=qwen&tags=story&hitsPerPage=8", path:"hits", comp:"阿里云百炼", lv:"P3"},
  {name:"HN·硅基流动 SiliconFlow", type:"API", url:"https://hn.algolia.com/api/v1/search_by_date?query=siliconflow&tags=story&hitsPerPage=8", path:"hits", comp:"硅基流动", lv:"P3"},
  {name:"HN·文心 ERNIE", type:"API", url:"https://hn.algolia.com/api/v1/search_by_date?query=ernie&tags=story&hitsPerPage=8", path:"hits", comp:"百度千帆", lv:"P3"},
  {name:"GitHub·Volcengine", type:"API", url:"https://api.github.com/search/repositories?q=volcengine&sort=updated&order=desc&per_page=6", path:"items", comp:"火山引擎方舟", lv:"P2"},
  {name:"GitHub·Qwen", type:"API", url:"https://api.github.com/search/repositories?q=qwen&sort=updated&order=desc&per_page=6", path:"items", comp:"阿里云百炼", lv:"P2"},
  {name:"GitHub·SiliconFlow", type:"API", url:"https://api.github.com/search/repositories?q=siliconflow&sort=updated&order=desc&per_page=6", path:"items", comp:"硅基流动", lv:"P2"},
  {name:"GitHub·Qianfan", type:"API", url:"https://api.github.com/search/repositories?q=qianfan&sort=updated&order=desc&per_page=6", path:"items", comp:"百度千帆", lv:"P2"}

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This is another client-side external transmission endpoint that will be contacted during live refresh. In a competitor-monitoring skill, such outbound requests can disclose what competitors or technologies the user is researching, creating avoidable privacy and business-intelligence leakage.

Content

Scanner excerpt · templates/report-demo.html (reported line 1022)May include surrounding context.

html
{name:"HN·硅基流动 SiliconFlow", type:"API", url:"https://hn.algolia.com/api/v1/search_by_date?query=siliconflow&tags=story&hitsPerPage=8", path:"hits", comp:"硅基流动", lv:"P3"},
  {name:"HN·文心 ERNIE", type:"API", url:"https://hn.algolia.com/api/v1/search_by_date?query=ernie&tags=story&hitsPerPage=8", path:"hits", comp:"百度千帆", lv:"P3"},
  {name:"GitHub·Volcengine", type:"API", url:"https://api.github.com/search/repositories?q=volcengine&sort=updated&order=desc&per_page=6", path:"items", comp:"火山引擎方舟", lv:"P2"},
  {name:"GitHub·Qwen", type:"API", url:"https://api.github.com/search/repositories?q=qwen&sort=updated&order=desc&per_page=6", path:"items", comp:"阿里云百炼", lv:"P2"},
  {name:"GitHub·SiliconFlow", type:"API", url:"https://api.github.com/search/repositories?q=siliconflow&sort=updated&order=desc&per_page=6", path:"items", comp:"硅基流动", lv:"P2"},
  {name:"GitHub·Qianfan", type:"API", url:"https://api.github.com/search/repositories?q=qianfan&sort=updated&order=desc&per_page=6", path:"items", comp:"百度千帆", lv:"P2"}
] };

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This configured third-party API endpoint participates in automatic outbound requests from the browser. Because the page auto-enables refresh, users may unknowingly contact external services, exposing network metadata and potentially sensitive usage patterns tied to competitive research.

Content

Scanner excerpt · templates/report-demo.html (reported line 1023)May include surrounding context.

html
{name:"HN·文心 ERNIE", type:"API", url:"https://hn.algolia.com/api/v1/search_by_date?query=ernie&tags=story&hitsPerPage=8", path:"hits", comp:"百度千帆", lv:"P3"},
  {name:"GitHub·Volcengine", type:"API", url:"https://api.github.com/search/repositories?q=volcengine&sort=updated&order=desc&per_page=6", path:"items", comp:"火山引擎方舟", lv:"P2"},
  {name:"GitHub·Qwen", type:"API", url:"https://api.github.com/search/repositories?q=qwen&sort=updated&order=desc&per_page=6", path:"items", comp:"阿里云百炼", lv:"P2"},
  {name:"GitHub·SiliconFlow", type:"API", url:"https://api.github.com/search/repositories?q=siliconflow&sort=updated&order=desc&per_page=6", path:"items", comp:"硅基流动", lv:"P2"},
  {name:"GitHub·Qianfan", type:"API", url:"https://api.github.com/search/repositories?q=qianfan&sort=updated&order=desc&per_page=6", path:"items", comp:"百度千帆", lv:"P2"}
] };
document.getElementById("srcBuiltin").innerHTML = BUILTIN_SOURCES.map(s=>

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This external endpoint is part of the hardcoded live data source set and results in third-party browser requests. While not exfiltrating secrets directly, it still creates a real external transmission channel that is inconsistent with a static demo and may leak organizational interest patterns or violate network policy.

Content

Scanner excerpt · templates/report-demo.html (reported line 1024)May include surrounding context.

html
{name:"GitHub·Volcengine", type:"API", url:"https://api.github.com/search/repositories?q=volcengine&sort=updated&order=desc&per_page=6", path:"items", comp:"火山引擎方舟", lv:"P2"},
  {name:"GitHub·Qwen", type:"API", url:"https://api.github.com/search/repositories?q=qwen&sort=updated&order=desc&per_page=6", path:"items", comp:"阿里云百炼", lv:"P2"},
  {name:"GitHub·SiliconFlow", type:"API", url:"https://api.github.com/search/repositories?q=siliconflow&sort=updated&order=desc&per_page=6", path:"items", comp:"硅基流动", lv:"P2"},
  {name:"GitHub·Qianfan", type:"API", url:"https://api.github.com/search/repositories?q=qianfan&sort=updated&order=desc&per_page=6", path:"items", comp:"百度千帆", lv:"P2"}
] };
document.getElementById("srcBuiltin").innerHTML = BUILTIN_SOURCES.map(s=>
  `<span class="src-chip"><span class="dot lv-dot-${s.lv}"></span>${s.n}<span class="lv" style="color:var(--${s.lv.toLowerCase()})">${s.lv}</span></span>`

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file is presented as a static demo page, but the init code enables live network fetching and periodic refresh on page load. That causes unsolicited outbound requests to third-party services from the user's browser, which is a real security/privacy issue because it leaks user IP, browser metadata, and potentially user-entered competitor context to external endpoints without an explicit opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Automatic network fetching on load and recurring refresh happen without a clear consent step. Even if the fetched data is public, initiating third-party requests from the browser without opt-in can expose user environment metadata and may violate enterprise browsing, privacy, or compliance expectations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown template forces a specific language/locale for all outputs, and there is no opt-in, alternative language option, or note that the skill is intentionally region-specific. Under the policy, language-only output without user choice can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.