Back to skill

Security audit

consulting-report-search

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but its report-detail fetch path can be steered to unexpected web addresses, so it needs review before installation.

Install only if you are comfortable with a networked report-search skill contacting iResearch and QuestMobile. Review or patch the script to restrict detail fetches to expected report hosts, require HTTPS, and validate redirects before using it in an environment with access to private internal services.

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
scripts/iresearch_report_search.py:425
Finding

Unrestricted Upstream-Controlled Report URL Fetch Enables SSRF

Content
View full analysis

Vulnerability Details

File Location: scripts/iresearch_report_search.py, lines 425–428, 471–478, 697, and 1079–1080
Vulnerability Type: Server-Side Request Forgery (SSRF) through insufficient URL validation
Risk Level: Medium

Vulnerable Code

python
def fetch_bytes(url: str, headers: dict[str, str]) -> bytes:
    """Fetch a URL and return raw bytes."""
    request = Request(url, headers=headers)
    with urlopen(request, timeout=20) as response:
        return response.read()
python
def normalize_report_link(url: str | None) -> str:
    """Normalize and validate a public report link."""
    value = clean_text(url or "")
    if not value:
        return ""
    if value.startswith("//"):
        return f"https:{value}"
    if value.startswith("http://") or value.startswith("https://"):
        return value
    return ""
python
detail_url=normalize_report_link(item.get("VisitUrl")),
python
detail_url = require_report_link(summary.detail_url)
html = fetch_html(detail_url)

Technical Analysis

The iResearch list API supplies the VisitUrl field. The script treats that field as a valid report URL whenever it starts with http://, https://, or a protocol-relative prefix. It does not enforce an allowlist of expected report hosts, require HTTPS, restrict destination ports, validate resolved IP addresses, or validate redirect destinations.

The accepted URL is later passed to urlopen(), which performs the request and follows HTTP redirects by default. Consequently, a compromised or malicious upstream API response could direct the script toward:

  • Loopback services such as 127.0.0.1
  • Private network services
  • Link-local destinations
  • Cloud instance metadata endpoints
  • Unexpected external hosts
  • An apparently legitimate host that redirects to one of these destinations

The user-supplied search query is ranked locally and is not sent to these report endpoints. The configured browser-like headers contain ...[truncated 1778 chars]

Remediation
View remediation

Remediation Suggestions

  1. Allowlist exact destination hosts

    • Permit only the report hosts required by the Skill, such as report.iresearch.cn.
    • Reject userinfo components, ambiguous hostnames, unexpected subdomains, and nonstandard ports.
    • Do not rely on substring or suffix checks that can be bypassed by domains such as report.iresearch.cn.attacker.example.
  2. Require HTTPS

    • Reject plaintext http:// URLs.
    • Preserve TLS certificate and hostname verification.
  3. Construct URLs from trusted identifiers

    • Prefer generating report detail URLs from validated numeric report IDs or known path formats.
    • Avoid fetching arbitrary VisitUrl values supplied by the remote API.
  4. Validate resolved addresses

    • Resolve the hostname before connecting.
    • Reject loopback, private, link-local, multicast, reserved, unspecified, and other non-public address ranges for both IPv4 and IPv6.
    • Account for DNS rebinding by ensuring the validated address is the address used for the connection.
  5. Control redirects

    • Disable automatic redirects or validate every redirect target using the same scheme, hostname, port, and resolved-address policy.
    • Set a small redirect limit.
  6. Apply response limits

    • Enforce a maximum response size and verify expected content types to reduce denial-of-service and unexpected-content risks.
    • Retain strict connection and read timeouts.
  7. Add security tests

    • Test rejection of localhost, RFC1918 ranges, IPv6 loopback, link-local addresses, cloud metadata addresses, encoded IP representations, protocol-relative URLs, credentials in URLs, nonstandard ports, and redirects to prohibited destinations.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill explicitly instructs use of networked resources and an exec tool to run a bundled script against external sites, but it does not declare an explicit tool scope such as permissions or allowed-tools. That creates an authorization ambiguity where an agent may invoke broader-than-expected network or execution capabilities, increasing the blast radius if the skill is misused or if the script behavior changes.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill mandates a fixed source-ordering and behavior centered on Chinese sources (iResearch first, QuestMobile second) without explicit user opt-in. While not directly code-execution dangerous, this can override user intent, force locale-specific behavior, and cause unintended network requests to region-specific services even when the user did not ask for that source preference.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation keywords include broad English triggers like report search and market research report, which are likely to match many ordinary user requests outside the intended niche. Over-broad activation can cause unintended routing into a networked, executable skill, leading to unnecessary external queries, data exposure in queries, or tool use when a simpler/local response would suffice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file contains natural-language instructions and field meanings in Chinese, and later mandates source grouping with Chinese-source-specific labels and anchors. Because the skill does not state that it is intentionally limited to Chinese-language research workflows or offer user opt-in for locale/language, this can violate the policy against forcing a specific language without user choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Multiple user-facing responses and rendered explanations are generated only in Chinese, such as the interpretation and answer text. This forces a specific language/locale in the skill's outputs without offering the user a language selection or documenting a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code performs HTTP requests to iResearch and QuestMobile via urlopen, and later sends user-supplied search queries or report identifiers in request URLs. While the module docstring says it fetches reports, there is no explicit user-facing warning at the network boundary, no logging/print about contacting third-party services, and no disclosure that user input may be transmitted to external sites.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.