Back to skill

Security audit

服装品类关键词挖掘专家

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches apparel keyword mining, but it sends sensitive LinkFox credentials and user data through environment-configurable endpoints and includes risky optional report-generation behavior.

Install only if you trust the LinkFox service and your environment variables. Before use, pin dependencies in a controlled environment, keep LINKFOX_TOOL_GATEWAY and related endpoint variables pointed only at trusted LinkFox hosts, avoid storing API keys in shell startup files when possible, and upload only files that are safe to make publicly accessible. Treat generated HTML reports as active content and open/share them cautiously.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
skills/linkfox-report-generator/scripts/inject_report.py:167
Finding

Arbitrary JavaScript Injection in Generated HTML Reports

Content
View full analysis
([\s\S]*?)", re.IGNORECASE, ) _CANVAS_BLOCK_RE = re.compile( r"([\s\S]*?)", re.IGNORECASE, ) _SCRIPT_OPEN_RE = re.compile(r"]*>", re.IGNORECASE) ``` ```python def _inject(template: str, content: str, title: str | None, language: str) -> str: # 1. Extract ECharts / Canvas blocks echarts_code = "" m = _ECHARTS_BLOCK_RE.search(content) if m: echarts_code = m.group(1).strip() echarts_code = _SCRIPT_OPEN_RE.sub("", echarts_code) content = _ECHARTS_BLOCK_RE.sub("", content).strip() canvas_code = "" m = _CANVAS_BLOCK_RE.search(content) if m: canvas_code = m.group(1).strip() canvas_code = _SCRIPT_OPEN_RE.sub("", canvas_code) content = _CANVAS_BLOCK_RE.sub("", content).strip() # 2. Replace document-level placeholders html = template.replace("{{TITLE}}", title or "LinkFox Analysis Report") html = html.replace("{{LANG}}", language) # 3. Inject the primary content html = re.sub( r".*?", "\n" + content + "\n", html, flags=re.DOTALL, ) # 4. Insert ECharts / Canvas initialization code into template markers if echarts_code: html = html.replace( "// ECHARTS_INIT_START\n // ECHARTS_INIT_END", "// ECHARTS_INIT_START\n " + echarts_code + "\n // ECHARTS_INIT_END", ) if canvas_code: html = html.replace( "// CANVAS_INIT_START\n // CANVAS_INI ...[truncated 2503 chars]
Remediation
View remediation
`, `&`, U+2028, and U+2029 when embedding JSON into HTML. 3. **Sanitize the HTML fragment.** - Use a maintained HTML sanitizer with a restrictive allowlist of required report elements, attributes, and CSS properties. - Remove event-handler attributes such as `onclick` and `onerror`. - Reject active elements such as `script`, `iframe`, `object`, `embed`, and `meta`. - Restrict URL-bearing attributes to approved HTTPS schemes and, where practical, approved hosts. 4. **Deploy a restrictive Content Security Policy.** - Move trusted scripts into separate static files. - Set a policy such as `default-src 'none'`, with narrowly scoped allowances for scripts, images, and styles. - Avoid both `'unsafe-inline'` and `'unsafe-eval'`. - Restrict outbound connections with `connect-src`. 5. **Add adversarial tests.** - Verify rejection of raw JavaScript, event attributes, script-closing sequences, `javascript:` URLs, SVG-based payloads, and encoded variants. - Confirm that valid ECharts and Canvas data continues to render without accepting executable code. ]]>

T08 · Insecure Dependencies

Warning
Location
skills/linkfox-aigc-textgen/scripts/onboarding.py:161
Finding

Unpinned Runtime Dependency Installation Instructions

Content
View full analysis
dict: try: import qrcode except ImportError: err = "缺少 qrcode 依赖,请运行: pip install qrcode pillow" print(f"{TAG} render_qr: {err}", file=sys.stderr) return {"png_path": None, "ascii_qr": None, "error": err} os.makedirs(out_dir, exist_ok=True) png_path = os.path.join(out_dir, f"qr-{int(time.time() * 1_000_000)}.png") qr = qrcode.QRCode(border=1) qr.add_data(content) qr.make(fit=True) qr.make_image(fill_color="black", back_color="white").save(png_path) buf = io.StringIO() qr.print_ascii(out=buf, invert=True) return {"png_path": png_path, "ascii_qr": buf.getvalue()} def _require_requests() -> None: if requests is None: raise RuntimeError("缺少 requests 依赖,请运行: pip install requests") ``` Equivalent unpinned installation advice is provided elsewhere for: ```text pip install oss2 pip install openpyxl pip install openai ``` ### Technical Analysis The project recommends installing third-party packages directly by name without specifying reviewed versions, cryptographic hashes, a lockfile, or a controlled package repository. Package names resolved by `pip` are mutable over time, so the code ultimately installed and imported may differ from the code considered during this audit. This pattern is especially sensitive in an Agent environment because imported Python packages execute with the same operating-system privile ...[truncated 1671 chars]
Remediation
View remediation
Vulnerability Patterns
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (98)

Tainted flow: 'req' from os.environ.get (line 335, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · skills/linkfox-aigc-textgen/scripts/aigc_textgen.py (reported line 237)May include surrounding context.

python
req = _lf_Request(url, headers={"User-Agent": "LinkFox-Skill/2.0"})
    try:
        with _lf_urlopen(req, timeout=timeout) as resp:
            if guessed_ext == "bin":
                ct = resp.headers.get("Content-Type", "")
                if "mp4" in ct:

Tainted flow: 'req' from os.environ.get (line 335, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · skills/linkfox-aigc-textgen/scripts/aigc_textgen.py (reported line 337)May include surrounding context.

python
}
    req = Request(url, data=data, headers=headers, method="POST")
    try:
        with urlopen(req, timeout=HTTP_TIMEOUT) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""

Tainted flow: 'url' from os.environ.get (line 235, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
93% confidence
Finding

The code builds destination URLs from environment-controlled base URLs and then sends sensitive data such as phone numbers, SMS codes, access tokens, refresh tokens, and API-token requests to those endpoints via requests.post. In a skill context, environment variables are often externally configurable, so a poisoned LINKFOX_LOGIN_API_URL or LINKFOX_AGENT_USER_API_URL could silently redirect credentials to an attacker-controlled server.

Content

Scanner excerpt · skills/linkfox-aigc-textgen/scripts/onboarding.py (reported line 196)May include surrounding context.

python
except RuntimeError as e:
        return {"_error": str(e)}
    try:
        r = requests.post(url, json=body or {}, headers=headers, timeout=timeout)
        return r.json()
    except Exception as e:
        body_text = ""

Tainted flow: 'req' from os.environ.get (line 244, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The gateway request path uses a URL derived from environment-controlled base configuration and sends authenticated requests with the LINKFOX_AGENT_API_KEY in the Authorization header. If LINKFOX_AGENT_API_URL or its fallback is altered, the tool can exfiltrate the API key and account/order data to an attacker-controlled endpoint.

Content

Scanner excerpt · skills/linkfox-aigc-textgen/scripts/onboarding.py (reported line 246)May include surrounding context.

python
headers["Content-Type"] = "application/json"
        req = Request(url, method=method, data=body_bytes, headers=headers)
        try:
            with urlopen(req, timeout=30) as resp:
                return json.loads(resp.read().decode())
        except urllib.error.HTTPError as e:
            status = e.code

Tainted flow: 'req' from os.environ.get (line 274, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · skills/linkfox-apparel-keyword-expert/scripts/linkfox_paths.py (reported line 504)May include surrounding context.

python
req = Request(url, headers={"User-Agent": "LinkFox-Skill/2.0"})
    try:
        with urlopen(req, timeout=timeout) as resp:
            # 从 Content-Type 进一步修正扩展名
            if guessed_ext == "bin":
                ct = resp.headers.get("Content-Type", "")

Tainted flow: 'req' from os.environ.get (line 274, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · skills/linkfox-report-generator/scripts/linkfox_paths.py (reported line 524)May include surrounding context.

python
req = Request(url, headers={"User-Agent": "LinkFox-Skill/2.0"})
    try:
        with urlopen(req, timeout=timeout) as resp:
            # 从 Content-Type 进一步修正扩展名
            if guessed_ext == "bin":
                ct = resp.headers.get("Content-Type", "")

Tainted flow: 'url' from os.environ.get (line 1708, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · skills/linkfox-apparel-keyword-expert/scripts/suggestion_miner.py (reported line 416)May include surrounding context.

python
try:
        if HAS_REQUESTS:
            resp = requests.get(url, headers=headers, timeout=15)
            if resp.status_code in (429, 503, 502, 500):
                raise RuntimeError(f"HTTP {resp.status_code}")
            data = resp.json()

Tainted flow: 'req' from os.environ.get (line 422, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · skills/linkfox-apparel-keyword-expert/scripts/suggestion_miner.py (reported line 423)May include surrounding context.

python
else:
            from urllib import request as urllib_request
            req = urllib_request.Request(url, headers=headers)
            with urllib_request.urlopen(req, timeout=15) as response:
                data = json.loads(response.read().decode('utf-8'))
    except Exception as e:
        if verbose:

Tainted flow: 'req' from os.environ.get (line 422, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
92% confidence
Finding

The LinkFox LLM helper constructs its gateway URL from the LINKFOX_TOOL_GATEWAY environment variable and sends prompts plus authorization headers to that endpoint. If an attacker can influence the environment, they can redirect sensitive product context, keyword data, and API credentials to an arbitrary server, creating an SSRF/exfiltration path.

Content

Scanner excerpt · skills/linkfox-apparel-keyword-expert/scripts/suggestion_miner.py (reported line 1711)May include surrounding context.

python
url = _GATEWAY + path
        data = json.dumps(body, ensure_ascii=False).encode("utf-8")
        req = _Request(url, data=data, headers=headers, method="POST")
        with _urlopen(req, timeout=120) as resp:
            return json.loads(resp.read().decode("utf-8"))

    # 1. Create task

Tainted flow: 'req' from os.environ.get (line 274, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

download_media accepts an arbitrary http/https URL and fetches it with urlopen, then writes the response to disk. This creates a real SSRF-style primitive and arbitrary remote content ingestion capability: an attacker controlling the URL can make the agent contact internal services, cloud metadata endpoints, or attacker infrastructure, which is especially risky because the skill's stated purpose does not require generic network fetching.

Content

Scanner excerpt · skills/linkfox-file-upload/scripts/linkfox_paths.py (reported line 524)May include surrounding context.

python
req = Request(url, headers={"User-Agent": "LinkFox-Skill/2.0"})
    try:
        with urlopen(req, timeout=timeout) as resp:
            # 从 Content-Type 进一步修正扩展名
            if guessed_ext == "bin":
                ct = resp.headers.get("Content-Type", "")

Tainted flow: 'req' from os.environ.get (line 60, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · skills/linkfox-keyword-library/scripts/keyword_library.py (reported line 75)May include surrounding context.

python
method="POST",
    )
    try:
        with urlopen(req, timeout=30) as response:
            return json.loads(response.read().decode("utf-8"))
    except HTTPError as e:
        body = e.read().decode("utf-8") if e.fp else ""

Tainted flow: 'req' from os.environ.get (line 274, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · skills/linkfox-apparel-keyword-expert/scripts/linkfox_paths.py (reported line 281)May include surrounding context.

python
headers={"Content-Type": "application/json", "Authorization": api_token},
        )
        try:
            with urlopen(req, timeout=30) as resp:
                body = json.loads(resp.read().decode())
            break
        except urllib.error.HTTPError as e:

Tainted flow: 'req' from os.environ.get (line 274, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · skills/linkfox-file-upload/scripts/linkfox_paths.py (reported line 281)May include surrounding context.

python
headers={"Content-Type": "application/json", "Authorization": api_token},
        )
        try:
            with urlopen(req, timeout=30) as resp:
                body = json.loads(resp.read().decode())
            break
        except urllib.error.HTTPError as e:

Tainted flow: 'req' from os.environ.get (line 274, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · skills/linkfox-report-generator/scripts/linkfox_paths.py (reported line 281)May include surrounding context.

python
headers={"Content-Type": "application/json", "Authorization": api_token},
        )
        try:
            with urlopen(req, timeout=30) as resp:
                body = json.loads(resp.read().decode())
            break
        except urllib.error.HTTPError as e:

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This finding again indicates undeclared local file I/O, directory/session management, upload-credential retrieval, OSS uploads, arbitrary HTTP(S) downloads, and text transformation utilities. In aggregate, these capabilities are much broader than a typical apparel keyword-mining assistant and could be abused for covert staging or transfer of user data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This finding again indicates undeclared local file I/O, directory/session management, upload-credential retrieval, OSS uploads, arbitrary HTTP(S) downloads, and text transformation utilities. In aggregate, these capabilities are much broader than a typical apparel keyword-mining assistant and could be abused for covert staging or transfer of user data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This finding again indicates undeclared local file I/O, directory/session management, upload-credential retrieval, OSS uploads, arbitrary HTTP(S) downloads, and text transformation utilities. In aggregate, these capabilities are much broader than a typical apparel keyword-mining assistant and could be abused for covert staging or transfer of user data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This finding again indicates undeclared local file I/O, directory/session management, upload-credential retrieval, OSS uploads, arbitrary HTTP(S) downloads, and text transformation utilities. In aggregate, these capabilities are much broader than a typical apparel keyword-mining assistant and could be abused for covert staging or transfer of user data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This finding again indicates undeclared local file I/O, directory/session management, upload-credential retrieval, OSS uploads, arbitrary HTTP(S) downloads, and text transformation utilities. In aggregate, these capabilities are much broader than a typical apparel keyword-mining assistant and could be abused for covert staging or transfer of user data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This finding again indicates undeclared local file I/O, directory/session management, upload-credential retrieval, OSS uploads, arbitrary HTTP(S) downloads, and text transformation utilities. In aggregate, these capabilities are much broader than a typical apparel keyword-mining assistant and could be abused for covert staging or transfer of user data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This finding again indicates undeclared local file I/O, directory/session management, upload-credential retrieval, OSS uploads, arbitrary HTTP(S) downloads, and text transformation utilities. In aggregate, these capabilities are much broader than a typical apparel keyword-mining assistant and could be abused for covert staging or transfer of user data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This finding again indicates undeclared local file I/O, directory/session management, upload-credential retrieval, OSS uploads, arbitrary HTTP(S) downloads, and text transformation utilities. In aggregate, these capabilities are much broader than a typical apparel keyword-mining assistant and could be abused for covert staging or transfer of user data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This finding again indicates undeclared local file I/O, directory/session management, upload-credential retrieval, OSS uploads, arbitrary HTTP(S) downloads, and text transformation utilities. In aggregate, these capabilities are much broader than a typical apparel keyword-mining assistant and could be abused for covert staging or transfer of user data.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

该文件明确是 linkfox-aigc-textgen 的 API 文档,而当前被评估技能是服装关键词挖掘工具,二者功能与命名不一致。这种跨技能引用会让当前技能获得与声明目的不匹配的生文与外部上报能力,造成能力边界混淆、错误数据流和潜在越权调用风险。

Content

No source excerpt is available for this finding.

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · skills/linkfox-aigc-textgen/references/onboarding.md (reported line 14)May include surrounding context.

md
示 JSON 里的 phone/agreements
   - 收到验证码后:`python scripts/onboarding.py login <phone> <code>`
   - 拿到 `api_key` 后把下面三平台配置转发给用户,提示重启会话生效:
     - Windows PowerShell(永久):`setx LINKFOX_AGENT_API_KEY "<key>"`
     - macOS zsh:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.zshrc && source ~/.zshrc`
     - Linux bash:`echo 'export LINKFOX_AGENT_API_KEY="<key>"' >> ~/.bashrc && source ~/.bashrc`
     - 变量名 `LINKFOX_AGENT_API_KEY`(主推)或 `LINKFOXAGENT_API_KEY`(老规范)任一即可

**billing 场景**:`errcode=402` 或消息含 `算力/余额/quota/insufficient/充值/套餐到期`。
- `python scripts/onboarding.py list-plans` → 有 AskUserQuestion 就弹菜单,否则输出编号清单让用户选
- 校验 `plan_id` ∈ 清单、支付方式 ∈ 该套餐 `available_methods`(通常 `wechat/alipay`)
- `python scripts/onboarding.py order <plan_id> <method>` → 展示优先级 PNG