Back to skill

Security audit

Business Information Inquiry Tool‌

Security checks for vulnerabilities and agentic risk

Overview

This enterprise-report skill is mostly purpose-aligned, but it has review-worthy risks from broad local credential discovery, unsafe API-key handling, and unescaped HTML report content.

Review this skill before installing in shared, enterprise, or sensitive workspaces. Prefer providing TAVILY_API_KEY only through an explicit environment variable, avoid placing unrelated secrets in .env files the skill can read, and do not host or redistribute generated HTML reports unless the unescaped-field issue is fixed or the report is sanitized.

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

Error
Location
scripts/html_generator.py:243
Finding

Mandatory Promotional and Named Contact Content in Generated Reports

Content
View full analysis
KINGDEE · 企业信息调研报告

Generated by KD-Enterprise-Info Skill v{version} | 反馈建议,请联系金蝶总部张贺老师

数据来源:{escape_html(sources)} | 报告日期:{report_date}

免责声明:本报告基于公开数据整理,仅供参考,不构成投资建议。

''' ``` The generated footer is inserted unconditionally through the following placeholder: ```python 'FOOTER_CONTENT': generate_footer(version, cleaned_data, time_str), ``` ### Technical Analysis Every generated company report receives a fixed brand attribution and a solicitation directing users to a specifically named contact. Callers cannot disable or replace this content through the documented interface. Although the Skill declares a Kingdee-inspired report style, the unavoidable insertion of named contact information is not necessary to search public company information or render an HTML report. This changes the requested output for an unrelated promotional purpose and creates misleading attribution risks when reports are redistributed. ### Attack Path 1. A user requests a company-information report. 2. The Agent invokes `generate_html()`. 3. `generate_html()` always calls `generate_footer()`. 4. The returned promotional footer is assigned to `FOOTER_CONTENT`. 5. Template replacement embeds the named contact solicitation into the final report. 6. Any recipient opening or receiving the report sees the unsolicited attribution and con ...[truncated 533 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/html_generator.py:280
Finding

HTML and JavaScript Injection Through Unescaped Report Fields

Content
View full analysis
{fallback_hint}' placeholders = { 'PAGE_TITLE': f'企业调研报告 - {escape_html(company_name)}', 'CSS_CONTENT': css_content, 'WARNING_BOX': warning_box, 'HEADER_ICON': '📊', 'HEADER_TITLE': '企业信息调研报告', 'COMPANY_NAME': company_name, 'DATA_DATE_LABEL': '数据截至时间', 'DATA_DATE_VALUE': cleaned_data.get('data_date', time_str.split(' ')[0]), 'META_LABEL': '生成时间', 'GENERATE_TIME': time_str, 'INSIGHT_TEXT_1': insight.get('market_size', MISSING_DEFAULT), 'INSIGHT_TEXT_2': insight.get('growth_driver', MISSING_DEFAULT), 'INSIGHT_TEXT_3': insight.get('policy_impact', MISSING_DEFAULT), 'INSIGHT_TEXT_4': insight.get('trend', MISSING_DEFAULT), 'INSIGHT_TEXT_5': insight.get('competition', MISSING_DEFAULT), 'INSIGHT_TEXT_6': insight.get('tech_direction', MISSING_DEFAULT), 'PROFILE_CONTENT_1': profile.get('introduction', MISSING_DEFAULT), 'PROFILE_CONTENT_2': profile.get('development', MISSING_DEFAULT), 'PROFILE_CONTENT_3': profile.get('culture', MISSING_DEFAULT), 'PROFILE_CONTENT_4': profile.get('honors', MISSING_DEFAULT), 'BASIC_VALUE_1': basic.get('name', company_name), 'BASIC_VALUE_2': basic.get('credit_code', MISSING_DEFAULT), 'BASIC_VALUE_3': basic.get('legal_person', MISSING_DEFAULT), 'BASIC_VALUE_4': basic.get('reg_capital', MISSING_DEFAULT), 'BASIC_VALUE_5': basic.get('paid_capital', MISSING_DEFAULT), 'BASIC_VALUE_6': basic.get('established', MISSING_DEFAULT), 'BASIC_VALUE_7': basic.get('status', ...[truncated 3628 chars]
Remediation
View remediation
` elements. - SVG and image event handlers. - Broken or nested tags. - Encoded HTML entities. - `javascript:` URLs. - Attribute-breaking quotes. 10. Test all placeholders, including error and fallback paths, rather than only helper-generated sections. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/enterprise_search.py:55
Finding

Tavily API Key Exposed in Request URL and Discovered From Overly Broad Secret Paths

Content
View full analysis
> ~/.openclaw/workspace/.env ``` ### Technical Analysis The optional Tavily integration legitimately needs a Tavily credential. However, the implementation exceeds the minimum file-access scope by searching multiple global and product-specific workspace locations, including a root-owned workspace, the user's home `.env`, and the current directory. The parser only returns a value whose name is exactly `TAVILY_API_KEY`; the reviewed code does not transmit unrela ...[truncated 1932 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (30)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 38)May include surrounding context.

方式一:环境变量

export TAVILY_API_KEY=your_tavily_api_key_here

方式二:写入 .env 文件(自动识别)

echo "TAVILY_API_KEY=your_tavily_api_key_here" >> ~/.openclaw/workspace/.env

text

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 39)May include surrounding context.

方式一:环境变量

export TAVILY_API_KEY=your_tavily_api_key_here

方式二:写入 .env 文件(自动识别)

echo "TAVILY_API_KEY=your_tavily_api_key_here" >> ~/.openclaw/workspace/.env

text

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill description materially misrepresents behavior: it claims built-in 11-dimension search and HTML generation, while the implementation reportedly depends on externally supplied results, performs narrower optional network access, and reads .env/environment variables. Security controls and user trust depend on accurate declarations; when behavior and documentation diverge, operators may authorize a skill under false assumptions, leading to secret access, unexpected data flows, and unsafe orchestration decisions.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
6. **AI 直接提取结构化数据**:AI 阅读全部搜索结果,直接构建 JSON 字典(示例见附表),传入 `html_generator.py` 生成报告。**不调用正则、不调用 query_enterprise**。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
6. **AI 直接提取结构化数据**:AI 阅读全部搜索结果,直接构建 JSON 字典(示例见附表),传入 `html_generator.py` 生成报告。**不调用正则、不调用 query_enterprise**。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
6. **AI 直接提取结构化数据**:AI 阅读全部搜索结果,直接构建 JSON 字典(示例见附表),传入 `html_generator.py` 生成报告。**不调用正则、不调用 query_enterprise**。

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
6. **AI 直接提取结构化数据**:AI 阅读全部搜索结果,直接构建 JSON 字典(示例见附表),传入 `html_generator.py` 生成报告。**不调用正则、不调用 query_enterprise**。

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

This hard-coded path is part of a routine that probes local .env files for API secrets, which is credential access beyond the narrow functional need of processing provided search text. In an agent runtime, such probing increases risk because the skill may access host secrets unrelated to the user's immediate task.

Content

Scanner excerpt · scripts/enterprise_search.py (reported line 57)May include surrounding context.

python
def get_tavily_key():
    """从环境变量读取 Tavily API Key"""
    env_paths = [
        '/root/.openclaw/workspace/.env',
        '~/.openclaw/workspace/.env',
        '~/.qclaw/workspace/.env',
        '~/.maxclaw/workspace/.env',

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

This line contributes to a multi-path search for local secret files, expanding the skill's credential access surface. Even if only one variable is extracted, the act of traversing common secret locations is inappropriate for a narrowly scoped enterprise search module.

Content

Scanner excerpt · scripts/enterprise_search.py (reported line 58)May include surrounding context.

python
"""从环境变量读取 Tavily API Key"""
    env_paths = [
        '/root/.openclaw/workspace/.env',
        '~/.openclaw/workspace/.env',
        '~/.qclaw/workspace/.env',
        '~/.maxclaw/workspace/.env',
        '~/.kimiclaw/workspace/.env',

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

By checking additional home-directory .env locations, the skill reaches into broader host configuration than users would reasonably expect. This increases the chance of unauthorized secret use and makes the module more dangerous in shared or enterprise environments.

Content

Scanner excerpt · scripts/enterprise_search.py (reported line 59)May include surrounding context.

python
env_paths = [
        '/root/.openclaw/workspace/.env',
        '~/.openclaw/workspace/.env',
        '~/.qclaw/workspace/.env',
        '~/.maxclaw/workspace/.env',
        '~/.kimiclaw/workspace/.env',
        '~/.env',

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

This path continues the pattern of credential discovery across multiple environments, which is a least-privilege violation. In combination with outbound HTTP requests, it can silently enable third-party data transfer using locally discovered credentials.

Content

Scanner excerpt · scripts/enterprise_search.py (reported line 60)May include surrounding context.

python
'/root/.openclaw/workspace/.env',
        '~/.openclaw/workspace/.env',
        '~/.qclaw/workspace/.env',
        '~/.maxclaw/workspace/.env',
        '~/.kimiclaw/workspace/.env',
        '~/.env',
        './.env',

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The code probes yet another local .env path for secrets, reinforcing a broad credential-access behavior not necessary for core functionality. Such host secret discovery is especially sensitive in agent skills, where trust boundaries should be narrow and explicit.

Content

Scanner excerpt · scripts/enterprise_search.py (reported line 61)May include surrounding context.

python
'~/.openclaw/workspace/.env',
        '~/.qclaw/workspace/.env',
        '~/.maxclaw/workspace/.env',
        '~/.kimiclaw/workspace/.env',
        '~/.env',
        './.env',
    ]

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Checking ~/.env expands access into a generic personal configuration file that may contain many unrelated credentials. This is dangerous because it normalizes broad secret inspection for a task that could function without touching user-level secret stores.

Content

Scanner excerpt · scripts/enterprise_search.py (reported line 62)May include surrounding context.

python
'~/.qclaw/workspace/.env',
        '~/.maxclaw/workspace/.env',
        '~/.kimiclaw/workspace/.env',
        '~/.env',
        './.env',
    ]
    for path in env_paths:

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Reading ./.env from the current working directory can unexpectedly pull credentials from unrelated projects, enabling network behavior with secrets outside the skill's ownership. This creates confusing and potentially unauthorized coupling between the skill and whatever repository it runs in.

Content

Scanner excerpt · scripts/enterprise_search.py (reported line 63)May include surrounding context.

python
'~/.maxclaw/workspace/.env',
        '~/.kimiclaw/workspace/.env',
        '~/.env',
        './.env',
    ]
    for path in env_paths:
        expanded = os.path.expanduser(path)

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

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

html
<body>
    <div class="container">

        <!-- ==================== 导航栏 ==================== -->
        <nav class="navbar animate-in">
            <div class="logo">{{HEADER_ICON}} {{HEADER_TITLE}}</div>
            <div class="nav-meta">

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The document emphasizes automatic web search and HTML report generation, but does not prominently warn that external retrieval and local/report artifact creation will occur. Users may not realize their query will cause network activity and persisted output, which can expose sensitive investigation targets or create unwanted artifacts.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README says the agent will auto-enable the skill whenever broad intent phrases like '企业调研' or '公司信息查询' appear with a company name. This creates a realistic risk of unintended activation, which can trigger network searches and report generation without sufficiently explicit user consent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

L136 明确写明海外企业查询“建议使用企业英文全称查询”,但整体文档、示例、输出风格与数据来源说明均默认中文语境,未说明是否支持用户选择其他语言输出。根据语言/locale 政策,若技能默认固定语言而无用户选择或充分的区域适用性说明,属于自然语言策略风险。

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares no explicit tool scope or permissions despite describing capabilities that involve environment-variable access, local file reads, and optional network calls. This creates an authorization and transparency gap: an agent or reviewer cannot reliably determine what resources the skill may access, increasing the chance of over-privileged execution or unintended secret exposure.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill says it supports natural requests such as “帮我查一下华为” and “做一份金蝶国际的企业背景调查报告”, but it does not define a constrained trigger boundary or exclusion conditions. Phrases like “帮我查一下…” are common everyday speech and could cause unintended invocation if used outside a clearly scoped command context.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The compliance comment claims the module does not collect privacy data, but the implementation later reads local .env files that may contain secrets or sensitive configuration. This mismatch is dangerous because it can mislead reviewers and users about the module's actual access to local sensitive data.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The function scans multiple local .env locations outside the immediate needs of a simple enterprise search helper, which broadens its access to secrets present on the host. Even though it only looks for TAVILY_API_KEY, reading arbitrary .env files violates least privilege and can expose unrelated sensitive configuration if the code is later extended, logged, or repurposed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill obtains Tavily credentials from local .env files without an obvious user-facing disclosure or consent boundary at the point of use. In an agent/skill context, silent secret discovery is risky because users may not expect the tool to inspect host configuration to enable networked behavior.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
87% confidence
Finding

The module sends user-derived enterprise search queries to the Tavily API, which is an external transmission to a third-party service. In this skill's context that behavior is somewhat expected, but it still carries data handling and privacy risk, especially because activation is tied to silently discovered credentials rather than explicit user opt-in.

Content

Scanner excerpt · scripts/enterprise_search.py (reported line 84)May include surrounding context.

python
if not key:
        return None
    try:
        url = f'https://api.tavily.com/search?api_key={key}&query={urllib.parse.quote(query)}&max_results={max_results}'
        req = urllib.request.Request(url)
        with urllib.request.urlopen(req, timeout=10) as resp:
            result = json.loads(resp.read().decode('utf-8'))

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file-level description and all user-facing text are written exclusively in Chinese, indicating the skill is designed to generate reports in a fixed language. Under the policy, forcing a specific language without explicit user opt-in or documented regional justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.