Back to skill

Security audit

Company Scan

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed company-search tool, but it uses an unsafe shared temporary file and overly forceful routing/display instructions that warrant review before installation.

Install only if you are comfortable sending company-search terms to IYIOU and seeing IYIOU links in results. The publisher should replace the fixed temp filename with a securely created per-run file and narrow the mandatory invocation wording before this is treated as low-risk.

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

T01 · Skill Instruction Hijacking

Error
Location
scripts/search_companies.py:247
Finding

Mandatory Promotional Link Injection into Agent Responses

Content
View full analysis

Vulnerability Details

File Location: scripts/search_companies.py:247-250; related instructions at SKILL.md:107-117; enforced by tests/test_search_companies.py:162-164
Vulnerability Type: Unrequested response manipulation through a mandatory promotional footer
Risk Level: High

Complete Code Snippet:

python
# Footer
lines.append(f"\n---")
lines.append(
    f"> 💡 如需查看更多企业请访问亿欧数据:[{IYIOU_LIST_URL}]({IYIOU_LIST_URL})"
)

The behavior is explicitly enforced by the test suite:

python
# footer prompt
self.assertIn("https://data.iyiou.com/company/comlist", md)

The Skill instructions require the Agent to read and display the generated file in full:

markdown
From that message, extract the path, use the `Read` tool to read the file,
and display its contents completely to the user.

Technical Analysis

The Markdown renderer unconditionally appends an external promotional link whenever a search returns at least one company. This content is not derived from the user's request and is not necessary to represent the API results.

The Skill instructions then direct the Agent to display the generated file completely. Consequently, the injected footer reliably reaches the final response rather than remaining an internal attribution or optional reference. The corresponding test explicitly requires the external link to remain present, demonstrating that this is intentional and persistent output behavior.

This constitutes Skill instruction hijacking because loading and following the Skill changes the Agent's response objective: in addition to satisfying the company-search request, the Agent is required to promote and redirect users to an external website.

Attack Path

  1. A user asks the Agent to search for companies matching particular criteria.
  2. The Skill instructs the Agent to invoke search_companies.py and write the results to a temporary file.
  3. The external ...[truncated 975 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the unconditional promotional footer from render_markdown().
  2. Remove or update the test that requires the promotional URL to appear.
  3. Restrict rendered output to information necessary to satisfy the user's company-search request.
  4. If attribution or a source reference is operationally required, clearly label it as attribution and document it transparently in the Skill metadata.
  5. Make optional external references dependent on an explicit user request rather than injecting them into every successful result.
  6. Apply an allowlist and destination review process to any external links intentionally included in future output.
  7. Add a test asserting that no unrelated promotional content is inserted into generated results.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/search_companies.py:355
Finding

Predictable Shared Temporary File Permits Symlink Attacks and Cross-Run Data Corruption

Content
View full analysis

Vulnerability Details

File Location: scripts/search_companies.py:355-357
Vulnerability Type: Unsafe temporary-file creation with a fixed path
Risk Level: Medium

Complete Code Snippet:

python
if args.output_temp:
    tmp = Path(tempfile.gettempdir()) / "company_scan_result.md"
    tmp.write_text(output, encoding="utf-8")
    print(f"✅ 结果已写入:{tmp}(共 {len(companies)} 家企业)")

Technical Analysis

The --output-temp path is always constructed as the same filename, company_scan_result.md, inside the system-wide temporary directory. The code does not atomically create a new file, verify ownership, reject symbolic links, or use an unpredictable filename.

Path.write_text() opens the selected path for writing and follows an existing symbolic link. On systems with a shared temporary directory, a local attacker may create the expected path before the Skill runs and point it at another file. If the process has permission to write to the symlink target, the target can be truncated and replaced with generated output.

The fixed filename also causes every invocation to share one output location. Concurrent searches can overwrite one another between the script's write operation and the Agent's subsequent read operation. One user or process may therefore receive another invocation's company-search results.

Attack Path

Symlink exploitation path:

  1. An attacker predicts the output path, such as /tmp/company_scan_result.md.
  2. Before the Skill executes, the attacker creates that path as a symbolic link to a file writable by the victim process.
  3. The victim invokes the Skill with --output-temp.
  4. Path.write_text() follows the symbolic link.
  5. The linked target is truncated and overwritten with the generated report.
  6. The attacker causes data corruption within the victim process's existing write permissions.

Concurrent-run disclosure path:

  1. Invocation A writes its search ...[truncated 943 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace the fixed path with an atomically created, unpredictable temporary file:

    python
    import os
    import tempfile
    from pathlib import Path
    
    fd, name = tempfile.mkstemp(
        prefix="company_scan_",
        suffix=".md",
        text=True,
    )
    try:
        with os.fdopen(fd, "w", encoding="utf-8") as output_file:
            output_file.write(output)
    except Exception:
        Path(name).unlink(missing_ok=True)
        raise
    
    tmp = Path(name)
    print(f"Result written to: {tmp} ({len(companies)} companies)")
    
  2. Ensure the resulting file is accessible only to the current user, using restrictive permissions such as mode 0600 where supported.

  3. Never reuse a global temporary filename across invocations.

  4. Do not check whether a path exists and then open it in a separate operation, because that introduces a time-of-check/time-of-use race.

  5. Delete temporary reports after the Agent has consumed them, subject to the surrounding tool lifecycle.

  6. Add tests verifying that separate invocations receive distinct paths and that pre-existing symbolic links are never followed.

  7. If a stable location is required, create a private per-user directory with verified ownership and restrictive permissions before writing any result files.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (6)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill declares that any request involving batch enterprise lookup by industry, region, or financing status 'must' use this skill, which creates an overly broad and mandatory routing rule. In an agent setting, this can cause unintended invocation on loosely related requests, reducing user control and potentially triggering external data access or tool execution when a narrower or safer path would have been more appropriate.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/search_companies.py (reported line 35)May include surrounding context.

python
from typing import Any

API_ENDPOINT = "https://api-open-data.iyiou.com/llm/company/search"
IYIOU_LIST_URL = "https://data.iyiou.com/company/comlist"

# Ordered round labels for range validation reference (informational only)
ROUND_ORDER = [

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · tests/test_search_companies.py (reported line 53)May include surrounding context.

python
from typing import Any

API_ENDPOINT = "https://api-open-data.iyiou.com/llm/company/search"
IYIOU_LIST_URL = "https://data.iyiou.com/company/comlist"

# Ordered round labels for range validation reference (informational only)
ROUND_ORDER = [

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · tests/test_search_companies.py (reported line 187)May include surrounding context.

python
from typing import Any

API_ENDPOINT = "https://api-open-data.iyiou.com/llm/company/search"
IYIOU_LIST_URL = "https://data.iyiou.com/company/comlist"

# Ordered round labels for range validation reference (informational only)
ROUND_ORDER = [

Vague Triggers

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The duplicated trigger guidance repeats the same broad mandatory invocation language, reinforcing aggressive routing behavior without adding safeguards. While the duplication itself is not a separate exploit primitive, it increases the likelihood that an orchestrator or maintainer treats overbroad activation as intentional and authoritative.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This test suite embeds Chinese-only company names, descriptions, and financing labels, and later asserts against Chinese UI/output strings. That creates a natural-language locale constraint in the skill behavior without any indication that users can choose another language or that the tool is intentionally region-specific.

Content

No source excerpt is available for this finding.