Back to skill

Security audit

Wininsales crm

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate WininSales CRM automation skill, but it needs Review because it can read and change sensitive CRM records and its examples use unsafe token-in-URL and shared temporary-file patterns.

Install only if you trust the WininSales CRM endpoint and are comfortable granting the agent access to CRM data and write actions under your account. Prefer a version that passes tokens through a protected secret or authorization header, avoids fixed temporary files, requires explicit confirmation for every write, and limits use to clearly identified CRM records.

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
SKILL.md:166
Finding

CRM Authentication Token Transmitted in URL Query String

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 166-185; repeated at lines 742-755
Vulnerability Type: Authentication credential exposure through URL query parameters
Risk Level: High

Vulnerable Code

bash
cat > /tmp/crm_query.json << 'JSONEOF'
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"ToolName","arguments":{"parameter":"value"}},"id":1}
JSONEOF
curl -s "https://www.wininsales.com/mcp_api/mcp?token=" \
  -X POST -H "Content-Type: application/json" \
  -d @/tmp/crm_query.json

The same invocation pattern appears again in the employee lookup and lead-assignment examples:

bash
cat > /tmp/crm_query.json << 'JSONEOF'
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"QueryEmployeeUserId","arguments":{"employee_name":"","multiple":0,"status":0}},"id":1}
JSONEOF
curl -s "https://www.wininsales.com/mcp_api/mcp?token=" \
  -X POST -H "Content-Type: application/json" \
  -d @/tmp/crm_query.json

cat > /tmp/crm_query.json << 'JSONEOF'
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"AssignLead","arguments":{"id":"LeadID","receiver":"","suggest":"Note"}},"id":1}
JSONEOF
curl -s "https://www.wininsales.com/mcp_api/mcp?token=" \
  -X POST -H "Content-Type: application/json" \
  -d @/tmp/crm_query.json

Technical Analysis

The documented API format places the CRM authentication token in the URL query string. Although the examples leave the token blank and explicitly warn against embedding a real token in the Skill file, an operational request would have to populate the query parameter.

URL query strings can be recorded by reverse proxies, load balancers, web-server access logs, application monitoring systems, debugging tools, command histories, process inspection tools, and error reports. HTTPS protects the request while it is in transit but does not prevent the complete URL from being recorded at either endpoint or in local tooling.

Because the document states that the token represents the current CR ...[truncated 1441 chars]

Remediation
View remediation

Remediation Suggestions

  1. Change the MCP API authentication design to accept credentials through an HTTP authorization header, for example:

    bash
    curl -s "https://www.wininsales.com/mcp_api/mcp" \
      -X POST \
      -H "Authorization: Bearer ${WININSALES_TOKEN}" \
      -H "Content-Type: application/json" \
      -d @request.json
    
  2. Obtain the token from a protected runtime secret source or environment variable rather than placing it directly in a command or file.

  3. Ensure authorization headers are redacted from application, proxy, and monitoring logs.

  4. Remove or redact query parameters from existing access logs and diagnostic data where feasible.

  5. Rotate any token that may previously have appeared in a URL, shell history, log, or support bundle.

  6. Use short-lived, revocable tokens with the minimum CRM permissions needed for each operation.

  7. Update every example in SKILL.md so that none encourages authentication through URL query parameters.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:174
Finding

Predictable Shared Temporary File Used for Sensitive CRM Requests

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 174-179 and 742-755
Vulnerability Type: Unsafe predictable temporary-file handling
Risk Level: Medium

Vulnerable Code

bash
cat > /tmp/crm_query.json << 'JSONEOF'
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"ToolName","arguments":{"parameter":"value"}},"id":1}
JSONEOF
curl -s "https://www.wininsales.com/mcp_api/mcp?token=" \
  -X POST -H "Content-Type: application/json" \
  -d @/tmp/crm_query.json

The fixed path is reused in later examples:

bash
cat > /tmp/crm_query.json << 'JSONEOF'
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"QueryEmployeeUserId","arguments":{"employee_name":"","multiple":0,"status":0}},"id":1}
JSONEOF
curl -s "https://www.wininsales.com/mcp_api/mcp?token=" \
  -X POST -H "Content-Type: application/json" \
  -d @/tmp/crm_query.json

cat > /tmp/crm_query.json << 'JSONEOF'
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"AssignLead","arguments":{"id":"LeadID","receiver":"","suggest":"Note"}},"id":1}
JSONEOF
curl -s "https://www.wininsales.com/mcp_api/mcp?token=" \
  -X POST -H "Content-Type: application/json" \
  -d @/tmp/crm_query.json

Technical Analysis

The instructions repeatedly write CRM request bodies to the fixed path /tmp/crm_query.json. The file is not securely created, assigned explicit restrictive permissions, validated as a regular file, or deleted after use.

A globally predictable path in a shared temporary directory creates several risks:

  • The resulting file may be readable by other local users when the process has a permissive umask.
  • CRM customer details, contact information, record identifiers, and operation parameters may remain on disk after the request.
  • Concurrent Skill invocations can overwrite one another's request bodies, causing data corruption or an unintended CRM operation.
  • On systems without effective temporary-file and symlink protections, an attacker can pre-create or race the p ...[truncated 2405 chars]
Remediation
View remediation

Remediation Suggestions

  1. Prefer avoiding temporary files entirely by generating the JSON in memory and sending it through standard input.

  2. If a temporary file is required, create a unique file securely:

    bash
    set -e
    umask 077
    request_file="$(mktemp "${TMPDIR:-/tmp}/crm_query.XXXXXX")"
    trap 'rm -f -- "$request_file"' EXIT HUP INT TERM
    
    cat > "$request_file" <<'JSONEOF'
    {"jsonrpc":"2.0","method":"tools/call","params":{"name":"ToolName","arguments":{"parameter":"value"}},"id":1}
    JSONEOF
    
    curl -s "https://www.wininsales.com/mcp_api/mcp" \
      -X POST \
      -H "Authorization: Bearer ${WININSALES_TOKEN}" \
      -H "Content-Type: application/json" \
      --data-binary "@${request_file}"
    
  3. Set umask 077 before creating files that may contain CRM data.

  4. Verify that the generated path is a regular file owned by the invoking user before use.

  5. Install cleanup handlers so temporary files are removed on normal exit, errors, and interruption.

  6. Never reuse one temporary path across concurrent requests.

  7. Avoid writing unnecessary personal information to disk and retain only the minimum request fields required.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (8)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 168)May include surrounding context.

md
- 上架技能包只能包含 `SKILL.md` 和必要的上架元数据,不能包含密码文件、运维脚本、数据库备份配置。

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill’s activation description is extremely broad and includes many generic CRM and sales-operations scenarios, making accidental invocation likely. Over-broad routing can expose sensitive CRM data or enable state-changing actions in contexts where the user did not clearly intend to use this specific skill.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The guidance says sensitive fields should be masked when displayed but allows full user-provided values to be used internally. In an LLM-driven skill, 'internally' often still means the raw data appears in prompts, tool arguments, logs, traces, or downstream systems, creating a real exposure and retention risk for phone numbers, emails, and other customer PII.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · SKILL.md (reported line 177)May include surrounding context.

cat > /tmp/crm_query.json << 'JSONEOF' {"jsonrpc":"2.0","method":"tools/call","params":{"name":"工具名称","arguments":{参数}},"id":1} JSONEOF curl -s "https://www.wininsales.com/mcp_api/mcp?token="
-X POST -H "Content-Type: application/json"
-d @/tmp/crm_query.json

text

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The workflow trigger phrases use vague everyday language like '记录一下跟进' and similar broad prompts without strong scope checks. That increases the chance the agent will enter this skill for ambiguous requests and perform CRM lookups or writes on the wrong customer, record, or account context.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · SKILL.md (reported line 286)May include surrounding context.

完整示例(客户分配):

bash
# Step 1: 查客户
curl ... -d '{"method":"tools/call","params":{"name":"SearchExistingCustomers","arguments":{"query":"XX公司"}}}'

# Step 2: 查员工ID(如果有权限)
curl ... -d '{"method":"tools/call","params":{"name":"QueryEmployeeUserId","arguments":{"employee_name":"张涛","multiple":0,"status":0}}}'

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · SKILL.md (reported line 745)May include surrounding context.

md
cat > /tmp/crm_query.json << 'JSONEOF'
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"QueryEmployeeUserId","arguments":{"employee_name":"","multiple":0,"status":0}},"id":1}
JSONEOF
curl -s "https://www.wininsales.com/mcp_api/mcp?token=" \
  -X POST -H "Content-Type: application/json" \
  -d @/tmp/crm_query.json

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · SKILL.md (reported line 879)May include surrounding context.

md
(以下由AI在实际调用中自动积累,请勿手动删除)

- SearchExistingCustomers / curl中文参数:shell直接传中文字符串到JSON时可能编码异常,建议用 heredoc 写入临时文件再 `curl -d @file`,或用 printf 管道传入
- AnalyzeCustomers / customer参数必须用公司全称:SearchExistingCustomers返回的company_name是什么就传什么,不能缩写或截断,否则查不到
- QueryDictByCode / 字典编码必须用全称:如 CompanyLevel、CompanyType、EmployeesNum、Industry,不能用 level、type、规模、行业 等简称或中文名,否则会导致查不到选项或选项不精准,进而影响客户/线索/商机录入
- CreateNewBusinessCustomer / 实际无contact_way/follow_up_way字段:CRMOperationManual声称有这两个字段但实际MCP schema中不存在,传入会被静默忽略

Static analysis

No suspicious patterns detected.