Back to skill

Security audit

cue-meeting-minutes-cn

Security checks for vulnerabilities and agentic risk

Overview

This meeting-minutes skill needs review because its connection checks can expose your API key and its validator rejects legitimate financial quotations.

Use the manual card workflow for confidential meetings unless you approve Cue processing and its data-handling terms. Before enabling credentialed checks, require validated destinations and blocked redirects. Preserve quoted financial amounts despite validator failures, and review fixed versions of optional dependencies before installing them.

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
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (25)

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 88)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 92)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 86)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 90)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
98% confidence
Finding

The supplied code does not read audio, enforce the recording-size limit, transcribe speech, or produce meeting minutes. Its implemented purpose is generic catalog discovery and authenticated connectivity testing, with no meeting-specific integration shown. Although connectivity checks can support a larger workflow, this chunk exposes independent service-discovery and credential-bearing network capabilities not represented in the declared description. HTTPS and destination-suffix checks constrain the initial authenticated request but do not resolve the purpose mismatch. Also, despite comments claiming no packets are sent by default, the default catalog path performs an anonymous HTTPS GET even without --post.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The supplied chunk performs service discovery and authenticated tool enumeration. It does not handle recordings, enforce the 256 MiB limit, transcribe audio, or generate source-anchored minutes. Remote tool discovery could support such a workflow, but this chunk establishes no meeting-specific connection and instead operates on a user-selected catalog domain. The mismatch concerns the supplied behavior; the code does not demonstrate recording uploads or credential theft.

Content

No source excerpt is available for this finding.

The credential destination guard applies only to the initial URL; automatic redirects can send the API key to an unauthorized host or over HTTP.

High
Category
Excessive Agency
Confidence
99% confidence
Finding

The destination guard checks only the initial URL, while urllib's default redirect handler can follow POST responses such as 301, 302, or 303 and preserve the Authorization header on the redirected request. An attacker able to influence an authorized endpoint's redirect could therefore receive the API key at an unauthorized host or over HTTP, defeating the script's credential-egress protections.

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.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

bash
# 1. Put it in the skills directory
mkdir -p ~/.workbuddy/skills
cp -r meeting-minutes-cn ~/.workbuddy/skills/

# 2. Copy the card template and fill it following section 1

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

bash
# 1. 放到技能目录
mkdir -p ~/.workbuddy/skills
cp -r meeting-minutes-cn ~/.workbuddy/skills/

# 2. 复制卡模板,按 §一 三步填

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

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The installation command uses an unpinned npx package and an unpinned skill repository, so the installed code and instructions can change without review. This is a supply-chain exposure rather than an unversioned MCP server specifically; compromise of either upstream could affect an agent handling sensitive meeting material.

Content

No source excerpt is available for this finding.

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

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

Selecting cue-omni-reader limits which skill is installed, but neither the npx executable package nor the repository revision is pinned. An upstream change or compromise could therefore introduce executable installer behavior or malicious agent instructions into the recording-processing workflow.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
98% confidence
Finding

The shell example sends CUE_API_KEY to a URL taken directly from the catalog without validating its scheme or authorized hostname. A compromised or misconfigured catalog could direct the credential to an attacker-controlled host or an HTTP endpoint; the separately documented script's destination checks do not protect users who follow this shell example.

Content

Scanner excerpt · README.en.md (reported line 97)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 parsing workflow requests spending consent but does not warn that meeting recordings are sent to an external service.

Medium
Category
Output Handling
Confidence
92% confidence
Finding

The consent step explicitly covers parsing spend and file counts, but does not clearly disclose that recording content will be transmitted to an external parsing service. The optional channel and service setup provide some context, but spending consent alone is not informed authorization to disclose potentially confidential meeting audio.

Content

No source excerpt is available for this finding.

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

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The command installing this skill also resolves an unpinned npx package and mutable repository content. Although this is ordinary installation guidance rather than evidence of malicious intent, it leaves users exposed to unreviewed upstream changes.

Content

No source excerpt is available for this finding.

The Cue parsing workflow lacks an explicit warning that meeting recordings may be transmitted to a third-party service.

Medium
Category
Output Handling
Confidence
90% confidence
Finding

The workflow introduces a remote parsing service without clearly stating that local recordings may leave the device for third-party processing. Asking users to confirm parsing consumption does not establish informed authorization to disclose enterprise meeting content, which may contain confidential or personal information.

Content

No source excerpt is available for this finding.

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

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The command invokes an unpinned npm installer and installs skills from an unpinned repository reference. Although this is not itself an MCP server declaration, changes or compromise upstream could introduce executable installer code or adversarial agent instructions into a workflow handling confidential meetings.

Content

No source excerpt is available for this finding.

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

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

Selecting only cue-omni-reader reduces installation scope but does not pin either the npm installer or the downloaded skill revision. An upstream compromise could therefore alter the parsing component that receives access to meeting material.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
98% confidence
Finding

Authenticating a tools/list request is expected, but this shell example sends the bearer credential to a URL taken directly from catalog data without validating its scheme or destination. A compromised or misconfigured catalog could redirect the credential to an attacker-controlled host or an HTTP endpoint; the separately described Python helper's safeguards do not protect this shell command.

Content

Scanner excerpt · README.md (reported line 95)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"}' \

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

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The self-installation command uses an unpinned npm installer and a mutable repository reference. Checking that the skill appears in the installed list proves presence, not integrity, so it does not mitigate supply-chain substitution.

Content

No source excerpt is available for this finding.

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 directs meeting recordings through a service-backed processing channel without a privacy or data-transfer warning.

Medium
Category
Output Handling
Confidence
86% confidence
Finding

The skill describes service-backed processing of local recordings without clearly identifying what leaves the local environment, the receiving provider, or an authorization step before transfer. Enterprise meeting recordings can contain confidential business information and personal data, making this omission a meaningful privacy risk if the channel uploads them; the supplied file does not establish an actual unauthorized transfer.

Content

No source excerpt is available for this finding.

L237–L238 reject prices anywhere in the minutes, including faithfully transcribed meeting content, despite the manifest promising verbatim, source-anchored minutes.

Medium
Category
Excessive Agency
Confidence
96% confidence
Finding

The validator rejects price-like expressions anywhere in the document, including accurately quoted, timestamped discussion of budgets or transaction amounts. This conflates unsupported service-pricing claims with legitimate meeting content and conflicts with the skill’s verbatim-recording purpose; if validation gates delivery, it can block valid minutes or pressure a downstream agent to omit material financial details. The script does not itself alter the minutes, so the integrity impact depends on how validation failures are handled.

Content

No source excerpt is available for this finding.

The documented default of sending no network packets contradicts the unconditional catalog fetch.

Medium
Category
Excessive Agency
Confidence
100% confidence
Finding

L010, L023, and the --post help at L133 explicitly claim that no packets are sent without --post. In fact, main calls read_catalog before checking --post, and L090–L093 perform an HTTPS GET unless --catalog-file is supplied. Users relying on the stated no-network default therefore contact the catalog service even when they only request address discovery or omit the required domain argument.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.