Back to skill

Security audit

持仓催化剂日历

Security checks for vulnerabilities and agentic risk

Overview

The calendar workflow is legitimate, but its connection instructions can expose your API key outside the intended service.

Use the user-supplied announcement path without configuring an API key until both connection methods enforce approved HTTPS destinations and reject unsafe redirects. Review dependency versions, consider whether sending issuer interests to Cue is acceptable, and manually verify calendar dates even when the checker reports PASS.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (30)

Tainted flow: 'req' from os.environ.get (line 188, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/cue_connectivity_check.py (reported line 193)May include surrounding context.

python
code = None
    raw = ""
    try:
        with urllib.request.urlopen(req, timeout=args.timeout) as resp:
            code, raw = resp.status, resp.read().decode("utf-8", "replace")
    except urllib.error.HTTPError as err:
        detail = ""

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

bash
CATALOG="https://cuecue.cn/api/mcp-catalog"
curl -s "$CATALOG" | python3 -c 'import json,sys
rows=json.load(sys.stdin)["data"]["domains"]
[print(r.get("id"), r.get("external_status"), (r.get("routing") or {}).get("url", "-")) for r in rows]'
DOMAIN_ID="<replace with one of the ids listed by the line above>"

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

md
rows=json.load(sys.stdin)["data"]["domains"]
[print(r.get("id"), r.get("external_status"), (r.get("routing") or {}).get("url", "-")) for r in rows]'
DOMAIN_ID="<replace with one of the ids listed by the line above>"
ROUTING_URL="$(curl -s "$CATALOG" | python3 -c 'import json,sys
rows=json.load(sys.stdin)["data"]["domains"]
hit=[r["routing"]["url"] for r in rows if r.get("id")==sys.argv[1] and r.get("routing")]
print(*hit,sep="\n") if hit else sys.exit("Not found: that id is not in the catalog response (or its routing has no url field) - run the line above and pick one of the ids listed")' "$DOMAIN_ID")"

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

bash
CATALOG="https://cuecue.cn/api/mcp-catalog"
curl -s "$CATALOG" | python3 -c 'import json,sys
rows=json.load(sys.stdin)["data"]["domains"]
[print(r.get("id"), r.get("external_status"), (r.get("routing") or {}).get("url", "-")) for r in rows]'
DOMAIN_ID="<把这里换成上一行列出的那个域 id>"

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

md
rows=json.load(sys.stdin)["data"]["domains"]
[print(r.get("id"), r.get("external_status"), (r.get("routing") or {}).get("url", "-")) for r in rows]'
DOMAIN_ID="<把这里换成上一行列出的那个域 id>"
ROUTING_URL="$(curl -s "$CATALOG" | python3 -c 'import json,sys
rows=json.load(sys.stdin)["data"]["domains"]
hit=[r["routing"]["url"] for r in rows if r.get("id")==sys.argv[1] and r.get("routing")]
print(*hit,sep="\n") if hit else sys.exit("未取到:该 id 不在目录现值里(或它没有 routing 里的 url 字段)——先跑上面那行列出现场的 id 再填")' "$DOMAIN_ID")"

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The supplied code does not process holdings, time windows, event disclosures, statutory dates, or calendar wording restrictions. Its primary function is service connectivity testing, including credential-backed network access, which is not represented in the declared purpose. Although authenticated POST requests require --post and pass initial HTTPS and authorized-host checks, these safeguards do not resolve the purpose mismatch. Without --post, the default path still performs an anonymous catalog GET unless a local catalog file is supplied. This is a materially different capability, not merely an implementation detail of the described calendar workflow.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The checker supports the declared calendar workflow, so its role as a validator rather than a generator is not itself a mismatch. However, the stated zero-tolerance policy is materially weaker in implementation: rating_offending exempts classification phrases outside the type column; prose containing a prohibition marker can bypass rating failures; sources.claim removes all 《…》 content before rating checks; and headings are skipped by prose scanning. Prohibited evaluative terms are also ignored inside 《…》 in table cells and prose. Furthermore, --evidence is optional, and when supplied it checks anchor occurrence in pooled evidence text, not whether the associated disclosure explicitly supplies the event date or whether statutory applicability and derivation are established. Thus a PASS does not enforce the description’s central admission guarantees.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

代码的直接用途是远程 MCP 服务发现、路由选择和工具枚举。它没有读取持仓或时间窗,也没有实现事件日期核验、法条适用条件校验、日历生成或评级词过滤。虽然远程服务调用可能成为其他流程的辅助环节,但所给代码未体现这些调用与声明的日历功能之间的关联,因此属于实质性用途不符。代码仅请求工具列表,未展示调用所列工具或执行交易。

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The supplied chunk implements remote service discovery and tool enumeration, not portfolio-event calendar generation. It does not process holdings or time windows, substantiate event dates, produce a calendar, or enforce the declared language restrictions. Although service discovery could support a larger application, this chunk establishes no connection between the selected endpoint and the declared calendar workflow. Its user-selected remote endpoint access and credential transmission are not represented in the description. The domain placeholder must be replaced before the authenticated request can succeed.

Content

No source excerpt is available for this finding.

Evidence validation checks anchor presence, not whether the evidence supports the event date.

High
Category
Excessive Agency
Confidence
99% confidence
Finding

Evidence matching establishes only that an anchor occurs somewhere in the evidence corpus; it does not establish that the cited source supports the row’s event, date, or statutory applicability. An attacker can pair a genuine announcement identifier with an invented event date and still satisfy these checks, undermining the skill’s central promise of evidence-grounded calendar dates. This is particularly consequential for financial monitoring, although the code acknowledges that deeper semantic verification requires human review.

Content

No source excerpt is available for this finding.

Automatic redirects can bypass the documented credential-destination guarantees.

High
Category
Excessive Agency
Confidence
99% confidence
Finding

The HTTPS and authorized-suffix checks apply only to the initial URL, while urllib.request.urlopen follows redirects automatically. For supported redirects such as 301, 302, or 303, urllib can forward the explicitly supplied Authorization header to a different host or an HTTP destination, so a malicious or compromised allowed endpoint—or an exploitable redirect there—can leak CUE_API_KEY despite the documented destination guarantees.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx skills'.

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

The workflow uses external Cue services to research the user's holdings without warning that issuer queries can disclose portfolio interests.

Medium
Category
Output Handling
Confidence
88% confidence
Finding

The workflow uses external services to investigate issuers supplied as the user's holdings, potentially exposing portfolio interests and linking them to an authenticated account. External service use is disclosed, but the document does not clearly explain this privacy implication; confirmation of spending is not equivalent to informed consent for portfolio-related disclosure.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx skills'.

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

The installation command invokes an unpinned npm executable and installs skill content from an unpinned repository reference. Although this is not itself an MCP server declaration, it creates a supply-chain risk: a compromised or unexpected upstream release could execute code or install adversarial agent instructions.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx skills'.

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

The collection-wide installation command leaves both the npm installer and repository content unpinned. Selecting skills limits what is installed but does not establish that the selected content matches a previously reviewed version.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx skills'.

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

The single-skill installation form also uses an unpinned executable and mutable skill source. Naming a specific skill narrows the installation scope but does not prevent a compromised upstream version from introducing executable code or malicious instructions.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
99% confidence
Finding

The shell example attaches the API key to a URL taken directly from the catalog without validating its scheme or authorized hostname. A compromised or malicious catalog entry could therefore direct the credential to an attacker-controlled endpoint or an insecure HTTP destination; the protections described for the separate Python helper do not protect this curl command.

Content

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

md
hit=[r["routing"]["url"] for r in rows if r.get("id")==sys.argv[1] and r.get("routing")]
print(*hit,sep="\n") if hit else sys.exit("Not found: that id is not in the catalog response (or its routing has no url field) - run the line above and pick one of the ids listed")' "$DOMAIN_ID")"
[ -n "$ROUTING_URL" ] || { echo "Fetch failed: ROUTING_URL is empty - run the line above, then set DOMAIN_ID to one of the ids listed" >&2; exit 1; }
curl -s -X POST "$ROUTING_URL" \
  -H "Authorization: Bearer $CUE_API_KEY" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \

The workflow does not warn that holdings-derived company identifiers will be sent to the external Cue service for research.

Medium
Category
Output Handling
Confidence
86% confidence
Finding

Researching the supplied holdings through Cue requires sending company identifiers derived from the user's portfolio to an external provider, but the README does not clearly disclose this privacy consequence. The external-service setup and requirement to ask before spending reduce surprise, but consent to service costs is not necessarily informed consent to sharing a holdings-derived query set.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx skills'.

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

The installation command uses an unpinned npx package and an unpinned skill repository reference, so its behavior can change without changes to this README. A compromised package release or repository update could execute malicious installer code or introduce adversarial agent instructions; this is a supply-chain issue rather than specifically an unpinned MCP server.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx skills'.

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

The collection-wide installation command retrieves an unpinned CLI and mutable third-party skill content. Installing several dependencies expands the supply-chain trust boundary, and the surrounding attribution to an official collection does not establish the integrity of the downloaded versions.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx skills'.

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

The single-skill installation variant also leaves both the npx CLI version and the upstream repository revision unpinned. Selecting one skill reduces installation scope but does not prevent a changed or compromised upstream artifact from supplying malicious code or agent instructions.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
99% confidence
Finding

The shell example sends CUE_API_KEY to a URL taken directly from the remote catalog without checking its scheme or host. Although the README describes destination checks in the separate Python helper, those checks are absent from this shell path, so a compromised or erroneous catalog response could direct the bearer credential to an attacker-controlled endpoint or an unencrypted HTTP destination.

Content

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

md
hit=[r["routing"]["url"] for r in rows if r.get("id")==sys.argv[1] and r.get("routing")]
print(*hit,sep="\n") if hit else sys.exit("未取到:该 id 不在目录现值里(或它没有 routing 里的 url 字段)——先跑上面那行列出现场的 id 再填")' "$DOMAIN_ID")"
[ -n "$ROUTING_URL" ] || { echo "取值失败:ROUTING_URL 为空——先跑上面那行列出现场 id,再把 DOMAIN_ID 换成其中之一" >&2; exit 1; }
curl -s -X POST "$ROUTING_URL" \
  -H "Authorization: Bearer $CUE_API_KEY" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \

Skill declares no tool scope ('permissions' or 'allowed-tools') but code capabilities were detected: env, file_read, network.

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

The workflow sends user-supplied portfolio subjects to external Cue services without a privacy warning.

Medium
Category
Output Handling
Confidence
94% confidence
Finding

The default workflow queries external services separately for user-supplied portfolio subjects without an explicit privacy notice or consent checkpoint. Individual company identifiers are public, but their association with a user and their aggregation can reveal confidential holdings or investment interests; the documented local-input fallback reduces necessity but does not address this disclosure.

Content

No source excerpt is available for this finding.

MCP server referenced without pinned version: 'npx skills'.

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

The documented installation commands use an unpinned npx package and mutable skill repositories, allowing the installed executable or skill instructions to change without review. Although the finding incorrectly describes npx as an MCP server, the underlying supply-chain exposure is real: a compromised upstream release could execute code or install malicious agent instructions with the user's privileges.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.