Back to skill

Security audit

多平台私信合并助手

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but its DingTalk fetch script can send app secrets and access tokens to unrestricted configured URLs.

Review before installing. Use only least-privilege DingTalk app credentials, verify the token URL and message API URL before running, and do not point DINGTALK_MESSAGES_API_URL or --token-url at any untrusted host. Store the generated inbox reports in a restricted location and delete them when no longer needed.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch_dingtalk_messages.py:40
Finding

Externally Controlled Endpoints Can Receive DingTalk Credentials

Content
View full analysis

Vulnerability Details

File Location: scripts/fetch_dingtalk_messages.py, lines 40–41, 52–55, and 65–67
Vulnerability Type: Credential disclosure through unrestricted network destinations
Risk Level: High

Vulnerable Code

python
ap.add_argument(
    '--token-url',
    default='https://api.dingtalk.com/v1.0/oauth2/accessToken'
)
ap.add_argument(
    '--messages-url',
    default=os.getenv('DINGTALK_MESSAGES_API_URL', ''),
    help='Your message query API URL'
)

token_resp = post_json(args.token_url, {
    'appKey': args.client_id,
    'appSecret': args.client_secret,
})

data_resp = post_json(args.messages_url, payload, headers={
    'x-acs-dingtalk-access-token': access_token,
})

The underlying request function sends the supplied data and headers using urllib.request.urlopen:

python
def post_json(url, data, headers=None):
    body = json.dumps(data).encode('utf-8')
    req = urllib.request.Request(url, data=body, method='POST')
    req.add_header('Content-Type', 'application/json')
    if headers:
        for k, v in headers.items():
            req.add_header(k, v)
    with urllib.request.urlopen(req) as resp:
        return json.loads(resp.read().decode('utf-8'))

Technical Analysis

The script sends two sensitive credentials to externally controllable destinations:

  1. --token-url receives the long-lived DingTalk client ID and client secret.
  2. --messages-url, or its DINGTALK_MESSAGES_API_URL environment-variable equivalent, receives the OAuth access token in an HTTP header.

No validation requires HTTPS, pins the token endpoint to the official DingTalk origin, restricts the message endpoint to an administrator-approved host, or rejects URLs containing user information. The use of urllib.request.urlopen also permits default redirect handling without an explicit same-origin restriction for credential-bearing requests.

A configurable enterprise message endpoint is consistent with the declared functionality b ...[truncated 1956 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the --token-url option and pin the authentication endpoint to the official DingTalk HTTPS URL. If endpoint customization is operationally unavoidable, enforce an exact administrator-controlled allowlist of schemes, hosts, ports, and paths.
  2. Require https for every endpoint that receives credentials. Reject plaintext HTTP and unexpected URL schemes.
  3. Validate --messages-url and DINGTALK_MESSAGES_API_URL against an explicit administrator-managed host allowlist before attaching the access token.
  4. Reject URLs containing embedded user information and, unless explicitly required, destinations resolving to loopback, link-local, private, multicast, or cloud-metadata address ranges. Revalidate after DNS resolution to reduce SSRF and DNS-rebinding risks.
  5. Disable redirects for credential-bearing requests, or permit only explicitly approved same-origin redirects. Never forward secrets or authorization headers across origins.
  6. Display the validated destination origin and require explicit approval before sending a token to a newly configured host.
  7. Apply least-privilege permissions to the DingTalk application and rotate both the client secret and active tokens if exposure is suspected.
  8. Add tests verifying rejection of HTTP URLs, unapproved hosts, cross-origin redirects, loopback addresses, link-local addresses, and cloud metadata endpoints.
  9. Avoid reporting complete authentication responses in errors, because provider responses may contain sensitive material. Return a sanitized error containing only the status and a non-sensitive provider error code.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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 (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill promises broad multi-platform inbox merging, deduplication, thread building, urgency scoring, and follow-up queue generation, but the described implementation appears materially incomplete and may only fetch or normalize DingTalk data. This mismatch is dangerous because users may rely on the output for operational decisions while assuming coverage, deduplication, and prioritization that do not actually exist, leading to missed messages, incorrect follow-up actions, and unsafe handling of sensitive communications.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
81% confidence
Finding

The script obtains an access token and then sends it to a user-configurable messages API URL via the x-acs-dingtalk-access-token header. Because --messages-url / DINGTALK_MESSAGES_API_URL is fully configurable and not restricted to trusted DingTalk domains, a misconfigured or malicious endpoint could capture the token and use it to access message data or related APIs.

Content

Scanner excerpt · scripts/fetch_dingtalk_messages.py (reported line 54)May include surrounding context.

python
})
    access_token = token_resp.get('accessToken')
    if not access_token:
        raise SystemExit(f'获取 access token 失败: {token_resp}')

    payload = {
        'limit': args.limit,

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill documents capabilities that require environment access, local file read/write, and network access, but it does not declare any explicit tool scope or permissions boundaries. This creates an overbroad-trust condition where a host agent may invoke the skill without clear authorization constraints, increasing the chance of unintended secret access, data exfiltration, or filesystem modification when handling sensitive inbox exports and API credentials.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The trigger phrases are broad enough to match common requests such as '统一收件箱' or '客户消息汇总', which can cause the skill to activate in contexts the user did not intend. Because this skill may read exported messages, fetch remote data, and process sensitive communications, accidental invocation increases privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The documentation instructs operators to obtain DingTalk access credentials and pull message data into local JSON files, but it provides no warning that the content may include sensitive business communications or that the credentials grant access to protected data. In a skill explicitly designed to aggregate messages across multiple platforms, this omission increases the chance of over-collection, insecure storage, or use without proper user authorization and handling controls.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file is natural-language documentation, and it presents all instructions and field explanations exclusively in Chinese. Under the language/locale policy, forcing a specific language without user opt-in or justification is a policy concern.

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 · scripts/fetch_dingtalk_messages.py (reported line 35)May include surrounding context.

python
ap = argparse.ArgumentParser(description='通过钉钉开放平台接口拉取消息并导出为 multi-inbox-merge 可读 JSON')
    ap.add_argument('--client-id', default=os.getenv('DINGTALK_CLIENT_ID', ''))
    ap.add_argument('--client-secret', default=os.getenv('DINGTALK_CLIENT_SECRET', ''))
    ap.add_argument('--token-url', default='https://api.dingtalk.com/v1.0/oauth2/accessToken')
    ap.add_argument('--messages-url', default=os.getenv('DINGTALK_MESSAGES_API_URL', ''), help='你的消息查询接口 URL(按企业应用能力配置)')
    ap.add_argument('--conversation-id', default='')
    ap.add_argument('--limit', type=int, default=100)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The script writes normalized DingTalk message content to a local JSON file, which can include sensitive business communications and personal data. In the context of a unified inbox skill that aggregates private messages, silent export increases the risk of unintended retention, overbroad access by other local users/processes, and accidental disclosure through backups or sync tools.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code writes merged messages, thread summaries, follow-up queues, and a markdown summary containing contact keys derived from emails, phone numbers, or user IDs. Although the script prints a completion message, it does not warn the user that sensitive inbox data will be consolidated and persisted to disk, and there is no docstring or comment disclosing that privacy impact.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

All user-facing instructions and examples are written only in Chinese, and the skill does not indicate that users may choose another language or locale. Under the language/locale policy, a skill should not implicitly force a specific language without opt-in unless the constraint is clearly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The user-facing argparse description and error messages are written only in Chinese. Under the language/locale policy, forcing a single language without opt-in can be a natural-language policy violation when no alternative or choice is provided.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code reads sensitive credentials from DINGTALK_CLIENT_ID and DINGTALK_CLIENT_SECRET, which falls under access to sensitive environment variables. While the script errors if they are missing, there is no comment, docstring, or explicit warning that it will read secrets from the environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script's comments, CLI help text, generated markdown headings, suggested actions, and status output are written only in Chinese. This imposes a single language/locale on users without any opt-in or documented justification, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.