Back to skill

Security audit

finstep-mcp

Security checks for vulnerabilities and agentic risk

Overview

This skill is mostly a financial-data API wrapper, but it needs review because it sends a secret in URL query strings and includes under-documented generic web/URL forwarding features.

Review before installing. Use a limited FinStep credential, avoid sending sensitive company or personal information in search terms or URLs, and be aware that generic web/URL parsing requests may disclose full URLs to FinStep. The publisher should move the signature out of query strings, document third-party data flows, and either remove or clearly gate the generic URL/web features.

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

Warning
Location
scripts/common.sh:10
Finding

API Signature Exposed in URL Query Strings

Content
View full analysis

Vulnerability Details

File Location:

  • scripts/common.sh:10-19
  • scripts/company.sh:11-20
  • scripts/macro.sh:10-19
  • scripts/plates.sh:11-20
  • scripts/quote.sh:10-19
  • scripts/search.sh:11-20

Vulnerability Type: Credential exposure through URL query parameters
Risk Level: Medium

Vulnerable Code

The following pattern appears in every service script:

bash
call_mcp() {
    local tool="$1"
    local params="$2"

    curl -s -X POST "${BASE_URL}?signature=${SIGNATURE}" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json, text/event-stream" \
        --max-time 30 \
        -d "$(jq -n --arg name "$tool" --argjson arguments "$params" \
            '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":$name,"arguments":$arguments}}')"
}

Technical Analysis

FINSTEP_SIGNATURE is explicitly designated as a secret in skill.json, but all scripts append it to the request URL as the signature query parameter.

HTTPS protects the complete URL while it is transmitted over the network, but it does not prevent the URL from being recorded at endpoints or intermediary infrastructure. Query strings are commonly retained in web-server access logs, reverse-proxy logs, application telemetry, tracing systems, monitoring platforms, and error reports.

Consequently, infrastructure components that legitimately record request URLs may unintentionally store a reusable authentication credential. The implementation conflicts with the project's own requirement that the signature be handled as confidential data.

Attack Path

  1. A user configures a valid FINSTEP_SIGNATURE in the environment.
  2. The user invokes any of the six service scripts.
  3. The script constructs a URL containing ?signature=<secret>.
  4. FinStep infrastructure, a reverse proxy, or an observability system records the complete request URL.
  5. An operator or ...[truncated 692 chars]
Remediation
View remediation

Remediation Suggestions

  1. Stop transmitting FINSTEP_SIGNATURE in the URL.

  2. Use a secret-bearing HTTP header supported by the server, for example:

    bash
    curl -sS -X POST "$BASE_URL" \
        -H "Authorization: Bearer ${SIGNATURE}" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json, text/event-stream" \
        --max-time 30 \
        --data "$request_body"
    
  3. If the API uses a proprietary authentication scheme, place the signature in a dedicated header rather than a query parameter.

  4. Configure servers, proxies, monitoring tools, and tracing systems to redact authentication values.

  5. Reject query-string credentials server-side after clients have migrated.

  6. Review historical logs for exposed signatures, restrict access to those logs, and rotate any credential that may have been recorded.

  7. Apply the correction consistently to all six scripts.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/common.sh:41
Finding

Undocumented Arbitrary URL Forwarding to Remote Parser

Content
View full analysis

Vulnerability Details

File Location: scripts/common.sh:41-44
Vulnerability Type: Unrestricted URL forwarding with potential server-side request forgery
Risk Level: Medium

Vulnerable Code

bash
url)
    # 解析网页内容
    URL="$2"
    call_mcp "url_parse" "$(jq -n --arg url "$URL" '{"url":$url}')"
    ;;

The supplied value is sent through the following remote API function:

bash
call_mcp() {
    local tool="$1"
    local params="$2"

    curl -s -X POST "${BASE_URL}?signature=${SIGNATURE}" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json, text/event-stream" \
        --max-time 30 \
        -d "$(jq -n --arg name "$tool" --argjson arguments "$params" \
            '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":$name,"arguments":$arguments}}')"
}

Technical Analysis

The url command accepts an arbitrary caller-controlled string and forwards it to the remote FinStep url_parse tool without validating the URL scheme, hostname, resolved address, embedded credentials, port, or redirect destination.

The command is also absent from the documented common-tool examples in README.md and SKILL.md, making this network-facing capability less visible during normal review.

If the remote url_parse implementation retrieves the supplied URL, this interface can act as a server-side request forgery primitive. The actual reachability and returned data depend on controls implemented by the FinStep backend, which are not present in the audited project. Even if private-network access is blocked remotely, URLs containing sensitive paths, query parameters, or embedded credentials are disclosed to the FinStep service.

Shell command injection was not identified in this code because jq --arg safely encodes the URL as a JSON string and the value is not evaluated as a shell command.

Attack Path

  1. A caller invokes `common.sh u ...[truncated 1104 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the url command if arbitrary webpage retrieval is not required for the Skill's declared financial-data purpose.
  2. If retained, document the capability and require explicit user authorization before sending a URL to the third-party service.
  3. Permit only required schemes, preferably https.
  4. Reject URLs containing embedded usernames or passwords.
  5. Enforce a strict hostname allowlist where practical.
  6. Resolve hostnames and reject loopback, private, link-local, multicast, reserved, and cloud-metadata address ranges.
  7. Repeat address validation after every DNS resolution and redirect to prevent DNS rebinding and redirect-based bypasses.
  8. Restrict destination ports and limit response size, retrieval time, and redirect count.
  9. Implement the same restrictions on the FinStep backend, because client-side validation alone cannot securely prevent SSRF.
  10. Avoid logging sensitive URL paths and query parameters, and return only sanitized parser output.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (32)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

该描述强调这是“全方位金融数据服务”,覆盖行情、板块、公司、宏观、研报新闻等多类金融查询场景。但代码仅封装了对远程 MCP 接口的 4 类调用:get_current_time、get_trade_info、get_trade_date 和 url_parse。其中只有交易日信息与金融/证券市场略有相关,且能力非常有限;而 url_parse 还是通用网页解析能力,与声明的金融数据服务主旨不一致。更重要的是,声明中的核心能力如实时行情、板块涨跌、公司财务、宏观数据、研报公告等在代码中完全未体现。因此描述与实际行为存在明显不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

声明描述的是“全方位金融数据”服务,范围明显大于该代码实际实现的能力。实际代码只覆盖市场行情及部分交易相关数据接口,并没有看到公司信息、财务、宏观经济、研报新闻或公告等功能入口,因此用户若按声明触发这些场景,代码无法满足。虽然实际功能仍属于金融数据范畴,主方向没有完全偏离,但声明对能力范围有显著夸大,同时代码还暴露了一些声明未明确列出的交易/行情细分能力。因此应判定为描述与实际行为不完全一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

声明描述的是“全方位金融数据服务”,重点覆盖实时行情、板块数据、公司信息、宏观经济、研报新闻等广泛金融数据场景。但代码仅根据 type 调用若干内容搜索接口,主要涉及 news/report/announcement/opinion/weixin/community/web 以及 morning 早报获取,本质上是资讯与内容检索工具。它没有任何处理股票实时行情、板块涨跌、公司财务报表、宏观经济指标等能力的实现。另一方面,代码还包含声明中未提及的 web 搜索、微信公众号搜索和社区论坛搜索。因此其实际行为与声明用途存在实质性偏差,属于描述与行为不一致。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The natural-language instructions and command descriptions are entirely Chinese, which can amount to a language-policy restriction if users are not given an opt-in choice or told the skill is intentionally region/language-specific. The documented service is A-share financial data, but the README does not explicitly state that the Chinese-only presentation is a justified locale constraint.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill documents shell-based execution (bash scripts with curl/jq) but does not declare any explicit tool scope such as allowed tools or permissions. That creates avoidable ambiguity about what the skill is permitted to execute and increases the chance an agent runtime grants broader shell access than is necessary for a data-retrieval skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill requires a secret token and documents remote API usage, but it does not clearly disclose that user queries and potentially system-provided context will be transmitted to a third-party service at fintool-mcp.finstep.cn. In an agent setting, this can lead to unintentional exfiltration of sensitive prompts, identifiers, or proprietary data through seemingly routine finance queries.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

This script is explicitly designed to transmit data to an external MCP service, so external transmission is expected in context; however, it still constitutes a real security concern because both user-supplied content and a sensitive signature are sent to a third-party endpoint. The risk is heightened by the financial-data context and the arbitrary URL parsing mode, which can cause unintended disclosure of user queries or sensitive targets to the remote service.

Content

Scanner excerpt · scripts/common.sh (reported line 14)May include surrounding context.

sh
local tool="$1"
    local params="$2"

    curl -s -X POST "${BASE_URL}?signature=${SIGNATURE}" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json, text/event-stream" \
        --max-time 30 \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script sends user-influenced parameters to a remote endpoint while also attaching a long-lived signature credential in the request URL, yet provides no disclosure, consent, or warning that user inputs will be transmitted off-box. Putting the credential in the query string increases exposure via logs, proxies, monitoring systems, and error traces, and the external transmission is especially relevant because the url mode can forward arbitrary user-supplied URLs to the service.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill exposes a generic url_parse capability that can fetch and process arbitrary user-supplied URLs, which goes beyond the narrowly described financial-data service purpose. This broadens the attack surface by enabling external content retrieval that may leak user-provided targets to the remote service and can be repurposed for unintended browsing, internal URL probing, or data exfiltration workflows through the MCP backend.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script sends the user-provided keyword and other query parameters to a remote HTTPS endpoint via curl, and includes the FINSTEP_SIGNATURE credential in the request URL. Although this behavior is central to the script's function, the code provides no user-facing warning, prompt, or visible disclosure that inputs and credentials are being transmitted to an external service.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/company.sh (reported line 15)May include surrounding context.

sh
local tool="$1"
    local params="$2"

    curl -s -X POST "${BASE_URL}?signature=${SIGNATURE}" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json, text/event-stream" \
        --max-time 30 \

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/macro.sh (reported line 14)May include surrounding context.

sh
local tool="$1"
    local params="$2"

    curl -s -X POST "${BASE_URL}?signature=${SIGNATURE}" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json, text/event-stream" \
        --max-time 30 \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script places the FINSTEP_SIGNATURE credential in the URL query string when calling the remote service. Query-string secrets are commonly exposed through logs, proxies, browser/history equivalents, monitoring systems, and upstream infrastructure, making accidental credential disclosure more likely even though HTTPS is used.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This script transmits data, including a credential-bearing request, to an external financial data service. External transmission is expected for this skill's purpose, but it remains security-relevant because user queries and the FINSTEP_SIGNATURE are sent off-host; combined with the URL-based secret handling, this increases risk of credential and query leakage.

Content

Scanner excerpt · scripts/plates.sh (reported line 15)May include surrounding context.

sh
local tool="$1"
    local params="$2"

    curl -s -X POST "${BASE_URL}?signature=${SIGNATURE}" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json, text/event-stream" \
        --max-time 30 \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script places the FINSTEP_SIGNATURE credential in the URL query string when calling the remote service. Query-string secrets are commonly exposed through shell history, process listings, proxy/server logs, monitoring systems, and referrer-like telemetry, making credential leakage more likely than if the secret were sent in an authorization header or request body.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/quote.sh (reported line 15)May include surrounding context.

sh
local tool="$1"
    local params="$2"

    curl -s -X POST "${BASE_URL}?signature=${SIGNATURE}" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json, text/event-stream" \
        --max-time 30 \

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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.sh (reported line 16)May include surrounding context.

sh
local tool="$1"
    local params="$2"

    curl -s -X POST "${BASE_URL}?signature=${SIGNATURE}" \
        -H "Content-Type: application/json" \
        -H "Accept: application/json, text/event-stream" \
        --max-time 30 \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This shell script performs an HTTP POST to an external endpoint and includes the FINSTEP_SIGNATURE credential in the request URL, but there is no confirmation prompt, visible user-facing notice, or explanatory warning near the network operation. For a code file, outbound transmission of credentials or potentially user-supplied query data should have some form of disclosure unless clearly surfaced elsewhere.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code posts data to a remote endpoint and includes both the user-supplied keyword and the FINSTEP_SIGNATURE credential, but there is no confirmation prompt, warning message, or explanatory note around that transmission. For a code file, outbound transmission of user/system data should have some visible disclosure unless clearly communicated elsewhere, which is not present in this file.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script exposes a generic web_search mode even though the skill metadata describes a finance-data service. That broadens the capability surface beyond the declared scope, which can bypass policy expectations, leak arbitrary user queries to an external search backend, and enable use cases the operator or user did not explicitly consent to.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill description states it should trigger for a very broad set of finance-related queries, including stock quotes, sector performance, company financials, macro data, and research/news, without clear activation boundaries. Over-broad triggering can cause the agent to invoke this skill in situations where it is not necessary, increasing unintended data access and expanding exposure of the required secret-backed external API.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file tells users to export FINSTEP_SIGNATURE, which is a credential-like value, but does not warn that it should be kept private and not committed, logged, or shared. Under the markdown criteria for missing user warnings, documentation should disclose privacy or credential-handling risks when user or system secrets are involved.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

The manifest description and the rest of the skill documentation are entirely in Chinese and present Chinese-language invocation/context as the default without any opt-in or language selection. The policy requires flagging language or locale constraints when the skill forces a specific language without user choice or explicit justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The user-facing comments and usage text are written only in Chinese, which imposes a specific language without any opt-in or alternative. Under the stated policy, language constraints should be optional or clearly justified rather than implicitly forced.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.