Back to skill

Security audit

Company Onepager

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to generate the promised stock report, but it handles financial-service credentials and cross-skill code in ways that need review before installation.

Install only if you are comfortable granting this skill access to your Tushare and iFinD credentials and letting it contact external financial/search services. Review or fix the disabled TLS verification, cross-skill Python import, output path validation, and Markdown/PDF sanitization before using it with valuable credentials or sensitive research targets.

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 (5)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_company_data.py:70
Finding

TLS Certificate Verification Disabled for Authenticated iFinD Requests

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_markdown_v6.py:31
Finding

Untrusted External Content Is Rendered Without HTML or Resource Sanitization

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/generate_markdown_v6.py:73
Finding

Runtime Execution of an Unverified Module from Another Mutable Skill Directory

Content
View full analysis
List[Dict]: """ Execute web_search through a system tool or Brave API. """ try: # Try to use the brave-search skill sys.path.insert( 0, os.path.expanduser( '~/.openclaw/workspace/skills/brave-search/scripts' ) ) from brave_search_api import brave_search return brave_search(query, count=count) except: # Return an empty list if brave-search is unavailable print(f" Web search: use system tool to search '{query}'") return [] ``` ### Technical Analysis The Skill prepends another Skill's mutable workspace directory to `sys.path`, then imports and executes `brave_search_api`. The imported file is outside this audited project and is not version-pinned or integrity-checked. Python executes module-level code immediately during import. Therefore, the imported module receives the same operating-system identity and process privileges as the report generator. It can access environment variables, local configuration files, report data, and network resources available to the process. Using `sys.path.insert(0, ...)` gives this directory the highest module-resolution priority. This also increases the potential for dependency shadowing if files in that directory use names matching other imported modules. ### Attack Path 1. An attacker or compromised Skill modifies: `~/.openclaw/workspace/skills/brave-search/scripts/brave_search_api.py`. 2. The victim invokes company report generation. 3. `fetch_company_info_from_web()` calls `web_search()`. 4. The mutable Brave Search directory is inserted at the beginning of `sys.path`. 5. Python imports `brave_search_api`. ...[truncated 804 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/onepager.py:22
Finding

Unvalidated Stock Code Can Influence Output Paths

Content
View full analysis
dict: """Create a listed-company one-page report.""" if not output_dir: output_dir = os.path.expanduser( f"~/.openclaw/workspace/temp/" f"onepager_{stock_code.replace('.', '_')}" ) os.makedirs(output_dir, exist_ok=True) data_file = os.path.join(output_dir, "data.json") chart_file = os.path.join(output_dir, "chart.png") md_file = os.path.join( output_dir, f"{stock_code.replace('.', '_')}_简报.md" ) pdf_file = os.path.join( output_dir, f"{stock_code.replace('.', '_')}_简报.pdf" ) ``` The standalone data-fetching path uses the same unvalidated value: ```python output_dir = os.path.expanduser( f"~/.openclaw/workspace/temp/" f"onepager_{stock_code.replace('.', '_')}" ) os.makedirs(output_dir, exist_ok=True) output_file = os.path.join(output_dir, "data.json") with open(output_file, 'w', encoding='utf-8') as f: json.dump(result, f, indent=2, ensure_ascii=False) ``` ### Technical Analysis The stock code is accepted directly from the command line and is used to construct directory and file names. The only transformation replaces periods with underscores. It does not reject path separators, traversal components, absolute-path syntax, control characters, or platform-specific path forms. The declared stock-code format is narrow, such as `600519.SH`, but the implementation does not enforce that format. If an untrusted caller can control the command-line argument, crafted path components can change where report files are created. The optional `--output` argument also allows arbitrary output locations by design. That beha ...[truncated 1345 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
SKILL.md:143
Finding

Third-Party Dependencies Are Installed Without Version or Integrity Pinning

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (26)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

该描述与代码存在实质不一致。描述强调这是一个‘生成一页纸调研简报’的技能,并承诺整合后输出 Markdown + PDF,还声明了 iFinD → Tushare → AkShare + Web Search 的数据优先级。实际代码是一个数据采集脚本,负责拉取多类股票/公司数据并保存为 JSON 文件,没有看到任何报告排版、Markdown 生成、PDF 导出或章节标注输出逻辑。数据来源方面,代码仅使用 Tushare 与 iFinD,没有 AkShare 或 Web Search 的实现;而且基本信息、市场数据、财务、K线、股东等主体内容主要都来自 Tushare,不符合‘iFinD 优先’的声明。另有一个额外能力是抓取公司近一年资本市场活动,这在描述中没有明确列为简报章节。综合来看,主功能被描述为“生成报告”,但代码实际只是“抓取并落盘数据”,因此应判定为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

This code chunk implements only a narrow sub-function: generating a 10-year monthly K-line style chart with turnover and Zigzag trend lines from already-supplied JSON data. The declared description presents a much broader end-to-end equity research brief generator with multi-source data acquisition, report composition, multiple content sections, and Markdown/PDF export. While the charting behavior is one component mentioned in the description, the actual code shown does not accurately represent the declared overall capability on its own. Therefore this chunk materially under-implements the declared purpose and has a different primary behavior.

Content

No source excerpt is available for this finding.

MCP Config Access

High
Category
Agent Snooping
Confidence
93% confidence
Finding

The skill explicitly references another skill's MCP config file path and instructs reading an auth_token from it. Accessing tokens from shared configuration locations is sensitive because it expands the blast radius across skills and can expose or misuse credentials intended for a different component.

Content

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

md
| 凭证 | 类型 | 配置方式 | 获取途径 |
|------|------|----------|----------|
| **TUSHARE_TOKEN** | 环境变量 | `export TUSHARE_TOKEN="your_token"` 或写入 `~/.bashrc` | https://tushare.pro |
| **iFinD auth_token** | 配置文件 | `~/.openclaw/workspace/skills/ifind-finance-data/mcp_config.json` 中的 `auth_token` 字段 | iFinD终端 → 工具 → 常用工具 → 数据MCP |

**配置示例:**

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
| `fetch_company_data.py` | 数据获取(iFinD→Tushare→AkShare降级) |

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises and instructs use of environment variables, local config files, shell execution, network access, and file output, but it does not declare any explicit tool/permission scope. This creates an over-privileged execution model where the agent may grant broader capabilities than users expect, increasing the risk of unintended secret access, network exfiltration, or filesystem modification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

该 markdown 文件整体以中文编写并将数据源规则、字段映射和调用示例固定为中文表述,但未说明这是仅面向中文用户或中国市场合规场景的限定,也未提供语言/locale 选择。根据规则,强制特定语言而无用户 opt-in 属于自然语言政策违规。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script's natural-language description and all user-facing console messages are fixed in Chinese, with no indication that language selection is optional or that the tool is intentionally limited to a Chinese-only audience. The policy calls for flagging language or locale constraints when they are forced without user opt-in or clear justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script reads an iFinD auth token from a local configuration file and transmits it in Authorization headers to an external service, while treating all content and network paths as trusted. If the configured endpoint is intercepted, misconfigured, or contacted over a weakened TLS setup elsewhere in the script, the credential can be exposed and reused to access the third-party account or associated data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code sends stock queries and an authorization token to the external iFinD service via HTTP requests, but the script provides no disclosure before transmission beyond generic progress messages. For code files, network calls that transmit user or system data should have some user-facing warning, confirmation, or clearly documented notice.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
99% confidence
Finding

The request disables TLS certificate verification with verify=False during session initialization to the external iFinD MCP endpoint. This makes the connection vulnerable to man-in-the-middle interception, allowing an attacker on the network path to spoof the server, capture the Authorization token, and tamper with returned data used in downstream report generation.

Content

Scanner excerpt · scripts/fetch_company_data.py (reported line 88)May include surrounding context.

python
}
        }
        
        resp = session.post(server_url, json=init_payload, headers=headers, verify=False, timeout=30)
        session_id = resp.headers.get("Mcp-Session-Id")
        
        if session_id:

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
99% confidence
Finding

The tool call to fetch company introduction data also disables TLS verification, exposing both the auth header and the returned content to interception or modification. Because the response content is incorporated into generated reports, an attacker could silently poison research output in addition to stealing credentials.

Content

Scanner excerpt · scripts/fetch_company_data.py (reported line 108)May include surrounding context.

python
}
        }
        
        resp = session.post(server_url, json=call_payload, headers=headers, verify=False, timeout=60)
        data = resp.json()
        
        if "result" in data:

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest describes a one-pager that integrates basic company info, market data, 10-year financial tables, 10-year monthly K-line charts, shareholder structure, and recent news. This file additionally retrieves '近一年资本市场活动(并购、投融资、回购、股权激励等)', which is a substantive extra content category not mentioned in the stated report scope or source-priority description.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
99% confidence
Finding

This capital-activities initialization request disables certificate verification, creating the same MITM exposure for session establishment and token transmission. An attacker could hijack the session setup and influence or observe all subsequent interactions with the external service.

Content

Scanner excerpt · scripts/fetch_company_data.py (reported line 418)May include surrounding context.

python
}
        }
        
        resp = session.post(server_url, json=init_payload, headers=headers, verify=False, timeout=30)
        session_id = resp.headers.get("Mcp-Session-Id")
        
        if session_id:

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
99% confidence
Finding

The capital-activities data request runs over a connection that does not verify server certificates, so returned activity data can be manipulated in transit. In a financial-research context, integrity of the fetched content matters; poisoned event data could mislead users and degrade trust while also exposing bearer credentials.

Content

Scanner excerpt · scripts/fetch_company_data.py (reported line 437)May include surrounding context.

python
}
        }
        
        resp = session.post(server_url, json=call_payload, headers=headers, verify=False, timeout=60)
        data = resp.json()
        
        if "result" in data:

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
99% confidence
Finding

The news-session initialization request also disables certificate validation, again exposing authentication material and session metadata to network attackers. Since the skill aggregates third-party news into saved output, tampering at this stage can undermine both confidentiality and integrity.

Content

Scanner excerpt · scripts/fetch_company_data.py (reported line 479)May include surrounding context.

python
}
        }
        
        resp = session.post(news_url, json=init_payload, headers=headers, verify=False, timeout=30)
        session_id = resp.headers.get("Mcp-Session-Id")
        
        if session_id:

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
99% confidence
Finding

The news search request transmits queries and receives content over a connection with verify=False, allowing interception and manipulation of both request and response. This is especially risky because the fetched content is later stored locally and may feed user-visible summaries or reports, making silent data poisoning plausible.

Content

Scanner excerpt · scripts/fetch_company_data.py (reported line 504)May include surrounding context.

python
}
        }
        
        resp = session.post(news_url, json=call_payload, headers=headers, verify=False, timeout=60)
        data = resp.json()
        
        if "result" in data:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The script's natural-language descriptions, headings, messages, and generated report content are consistently fixed in Chinese, indicating the skill forces a specific language/locale. There is no apparent user opt-in or configurable language selection to accommodate different locale preferences.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation says the function gets company information via the OpenClaw system web_search tool, implying actual search execution. In practice, the code modifies sys.path to import a local brave_search_api module, and if that import fails it only logs a message and returns an empty list rather than calling any system tool.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill sends company-derived queries to an external search provider without explicit user consent or a clear notice that report generation causes outbound network transmission. In environments where queried entities, watchlists, or internal research targets are sensitive, this can leak confidential business interest or workflow context to third parties.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The function documentation promises actual web search execution through either a system tool or Brave API. However, the except branch only prints that it will use a system tool and immediately returns an empty list, so the documented behavior contradicts what the code really does.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring and subsequent user-facing messages are written in Chinese, which imposes a specific language on users without any opt-in or indication that the tool is intentionally limited to a Chinese-speaking context. The policy explicitly calls for flagging language or locale constraints when they are forced rather than optional or justified.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/generate_pdf.py (reported line 196)May include surrounding context.

python
def generate_pdf_pypdf(html_path: str, pdf_path: str) -> bool:
    """使用 wkhtmltopdf 作为备选"""
    try:
        result = subprocess.run(
            ['wkhtmltopdf', '--encoding', 'utf-8', html_path, pdf_path],
            capture_output=True, text=True
        )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code file contains natural-language strings and documentation that force a specific language for descriptions, CLI help, and status output. Under the policy, a skill should not impose a language or locale without user opt-in or clear justification that the tool is region-specific.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The docstring at L448 states the function gets recent news '用于模型汇总摘要', implying summarization-oriented behavior. In practice, the function only queries iFinD, parses results, and returns raw news entries; no model call or summarization occurs in this code path.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script creates a directory and writes aggregated company data to ~/.openclaw/workspace/temp/.../data.json, but there is no prior warning or explanatory comment describing that local files will be created. Although it prints the saved path afterward, the operation lacks advance disclosure about file creation and persistence.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.