Back to skill

Security audit

iFinD投研-公司公告信息搜索

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its announcement-search purpose, but it can store a token and later send it to an arbitrary configured server.

Review before installing. Use this only if you trust the publisher and need the iFinD/RePilot announcement API. Do not use --set-url unless you fully trust the destination; verify ~/.config/ifind-repilot/config.json keeps base_url on the official repilot.51ifind.com service, protect the token like a password, and rotate it if it may have appeared in shell history, logs, or a misconfigured endpoint.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_data.py:35
Finding

Authentication Token Can Be Sent to an Arbitrary Configurable Endpoint

Content
View full analysis

Vulnerability Details

File Location: scripts/fetch_data.py:35-38, scripts/fetch_data.py:88-98, and scripts/fetch_data.py:178-185
Vulnerability Type: Unrestricted authentication endpoint configuration
Risk Level: High

Vulnerable Code

python
def get_base_url():
    """Get the base URL."""
    config = get_config()
    return config.get("base_url", DEFAULT_BASE_URL).rstrip("/")
python
token = get_token()
base_url = get_base_url()

params = {"query": query, "skillCode": SKILL_CODE}
if start_date:
    params["startDate"] = start_date
if end_date:
    params["endDate"] = end_date

query_string = urllib.parse.urlencode(params)
url = f"{base_url}/research_pilot_service/openapi/skills/open/search/announcement?{query_string}"

request = urllib.request.Request(url)
request.add_header("Authorization", token)
request.add_header("Content-Type", "application/json")
python
if sys.argv[1] == "--set-url":
    if len(sys.argv) < 3:
        print("Error: provide a URL value", file=sys.stderr)
        print("Usage: python fetch_data.py --set-url <url>", file=sys.stderr)
        sys.exit(1)
    set_config("base_url", sys.argv[2])
    sys.exit(0)

Technical Analysis

The script permits base_url to be replaced with an arbitrary value through the undocumented --set-url command. No scheme validation, HTTPS requirement, hostname allowlist, or origin check is applied. The same code then unconditionally attaches the configured authentication token to the Authorization header.

Consequently, changing the endpoint causes subsequent queries to disclose the token to the configured server. Allowing an http:// endpoint also exposes the token, query, and response to plaintext network interception. Depending on network access, arbitrary endpoint support may additionally allow requests to internal services, although the fixed API path limits the reachable req ...[truncated 1613 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the --set-url feature if alternate endpoints are not essential to the declared functionality.
  2. If endpoint customization is required, parse the URL with urllib.parse.urlparse and enforce:
    • The https scheme.
    • An explicit allowlist of trusted hostnames.
    • An expected port.
    • Rejection of embedded credentials, fragments, IP literals, loopback addresses, and private or link-local destinations where they are not required.
  3. Only attach the Authorization header after verifying that the final request origin is trusted.
  4. Prevent redirects from forwarding credentials to a different origin, or disable redirects and validate each redirect destination.
  5. Store endpoint configuration separately from credentials and warn or fail closed if the endpoint is invalid.
  6. Document every supported endpoint override and its security implications.
  7. Add tests confirming that HTTP, unapproved domains, localhost, private addresses, and cross-origin redirects are rejected.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fetch_data.py:142
Finding

Authentication Token Is Exposed Through Process Arguments and Insufficiently Protected Plaintext Storage

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:26-34, scripts/fetch_data.py:142-149, and scripts/fetch_data.py:171-177
Vulnerability Type: Insecure credential input and storage
Risk Level: Medium

Vulnerable Code

bash
python3 <skill_dir>/scripts/fetch_data.py --set-token <your_auth_token>
python
def set_config(key: str, value: str):
    """Set a configuration item."""
    CONFIG_DIR.mkdir(parents=True, exist_ok=True)

    config = get_config()
    config[key] = value

    with open(CONFIG_FILE, "w") as f:
        json.dump(config, f, indent=2)
python
if sys.argv[1] == "--set-token":
    if len(sys.argv) < 3:
        print("Error: provide a token value", file=sys.stderr)
        print("Usage: python fetch_data.py --set-token <token>", file=sys.stderr)
        sys.exit(1)
    set_config("auth_token", sys.argv[2])
    sys.exit(0)

Technical Analysis

The documented setup procedure requires users to place the authentication token directly in a command-line argument. Depending on the operating system and shell configuration, command-line arguments may be visible in process listings, process monitoring tools, audit logs, terminal records, and shell history.

The token is then persisted as plaintext JSON. Although the effective permissions of a newly created file depend on the user's umask, the script does not explicitly create the configuration directory with mode 0700 or the token file with mode 0600. It also does not repair an existing file with overly broad permissions. On a multi-user system or a system with permissive defaults, another local account may therefore be able to read the token.

Storing a token locally is functionally necessary unless a secret manager or environment-based workflow is used. However, exposing it through command-line arguments and relying only on ambient permission defaults are not minimum-risk implemen ...[truncated 1462 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the token-valued command-line argument with an interactive hidden prompt using getpass.getpass().
  2. Optionally support reading the token from standard input, an environment variable, or an operating-system credential store, while documenting the security trade-offs of each mechanism.
  3. Remove examples that place real tokens directly in shell commands.
  4. Create ~/.config/ifind-repilot with mode 0700.
  5. Create the configuration file atomically with mode 0600, and explicitly apply chmod(0o600) to existing files before storing credentials.
  6. Reject configuration files not owned by the current user or files that are symbolic links.
  7. Consider storing the token in the platform keychain or a dedicated secret-management service instead of plaintext JSON.
  8. Ensure errors and status messages never print the token.
  9. Add automated tests that verify owner-only permissions and confirm that token values do not appear in process arguments or program output.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill performs network access and writes credentials to a local config file, but it declares no explicit tool scope or permissions boundaries. This can lead to overbroad execution in agent environments, reducing transparency and making it easier for the skill to access network or persist data without clear user awareness or policy enforcement.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill states that it sends user queries to an external data interface, but it does not clearly disclose to end users that their query content will leave the local environment. Because queries may contain sensitive financial research intent, company names, or other confidential context, the lack of transmission notice can cause unintended data exposure to a third-party service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation instructs the user to provide an auth token and store it via a script, but gives no warning about treating the token as sensitive, how it will be stored, or who can access it. This creates a real risk of credential mishandling, accidental disclosure in chat, shell history, logs, or insecure file permissions on the config file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code file contains natural-language documentation and CLI help entirely in Chinese, and the script surfaces all user-facing usage and error messages in Chinese only. Under the language/locale policy, forcing a specific language without user opt-in is a policy concern unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script is described as a search utility, but it also persists secrets locally and allows runtime reconfiguration of the backend via --set-url. That combination enables token exfiltration or redirection of authenticated requests to an attacker-controlled endpoint if a user is induced to change the base URL, which is especially risky because the same stored auth_token is then sent in the Authorization header.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.