Back to skill

Security audit

WeChat Pay Integration

Security checks for vulnerabilities and agentic risk

Overview

This WeChat Pay helper is not deceptive, but it needs Review because its copy-paste payment callback and refund examples include unsafe financial-handling patterns.

Review carefully before installing or using. Treat the examples as reference material only, not production-ready code. Before deployment, replace callback verification with real WeChat Pay platform certificate/public-key verification over the raw request body, fail closed on verification or processing errors, use durable database-backed idempotency and order/amount/currency validation, protect merchant keys and APIv3 secrets, remove unsafe dependency commands, and test all payment/refund flows with controlled credentials.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (7)

T09 · Insecure Skill Coding Practices

Error
Location
references/代码示例/Node.js/回调处理/回调处理.md:34
Finding

Payment callback signature verification is unconditionally bypassed

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/代码示例/Node.js/回调处理/回调处理.md:100
Finding

Node.js callback verification reconstructs JSON instead of using the signed raw body

Content
View full analysis
{ const body = JSON.stringify(req.body); const headers = { 'wechatpay-timestamp': req.headers['wechatpay-timestamp'], 'wechatpay-nonce': req.headers['wechatpay-nonce'], 'wechatpay-signature': req.headers['wechatpay-signature'], 'wechatpay-serial': req.headers['wechatpay-serial'] }; ``` ### Technical Analysis WeChat Pay signs the exact HTTP request-body bytes. The example first parses the request through `express.json()` and then recreates it with `JSON.stringify(req.body)`. JSON parsing and serialization can change whitespace, escaping, numeric representation, or other byte-level details without changing the parsed object. A correct RSA verifier operating on the reconstructed value can therefore reject an authentic callback. This problem remains even if the later sample verification logic is implemented correctly. ### Attack Path 1. WeChat Pay sends a valid callback whose signature covers the original JSON bytes. 2. `express.json()` parses the body. 3. `JSON.stringify(req.body)` creates a potentially different byte sequence. 4. Signature verification is performed against the reconstructed body. 5. Verification fails despite the callback being authentic. 6. The handler’s error path acknowledges the failed callback as successful, preventing an upstream retry. ### Impact Assessment Legitimate payment and refund notifications can be lost. This can leave paid orders unfulfilled, prevent refund status updates, and create discrepancies between the merchant database and WeChat Pay. The affected scope is the callback-processing workflow rather than host-level privileges. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/代码示例/Node.js/回调处理/回调处理.md:162
Finding

Node.js callback processing failures are acknowledged as successful

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/代码示例/Python/回调处理/回调处理.md:239
Finding

Python callback processing failures are acknowledged as successful

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/代码示例/Python/回调处理/回调处理.md:39
Finding

Python callback verification cannot succeed because platform-key retrieval is unimplemented

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
references/代码示例/Node.js/回调处理/回调处理.md:107
Finding

Payment callback examples use non-durable idempotency and omit mandatory order validation

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
references/代码示例/Node.js/JSAPI支付/JSAPI支付.md:7
Finding

Dependency instructions install Node.js core-module names from the public npm registry

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (39)

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The primary sample claims to receive, verify, decrypt, and process WeChat Pay callbacks, but its verifySignature function always returns true. That means any attacker who can reach the callback endpoint can forge payment or refund notifications and potentially trigger business logic such as marking orders paid or issuing goods without a real WeChat-signed message.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The document's security guidance says signature verification is mandatory, but the main sample contradicts that guidance by not performing real verification. In a developer-focused payment integration skill, this inconsistency is dangerous because users are likely to copy the first complete example and assume it is safe, leading to insecure callback handling in production.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The exception path always returns a success response even when signature verification fails or business processing throws an error. In payment callbacks, acknowledging failed verification or failed processing can suppress legitimate retries, causing missed payments, inconsistent order state, and making forged or malformed notifications harder to detect and recover from.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The callback handler explicitly notes that signature verification is required, but the code proceeds to decrypt and process refund notifications without verifying the WeChat Pay signature or certificate serial. An attacker who can reach the callback endpoint could submit forged notifications that trigger false refund status updates, causing fraudulent state changes or financial reconciliation errors.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill advertises behaviors that require reading local reference files and using network access (for example via curl), but it does not declare any explicit tool scope such as permissions or allowed-tools. In an agent environment, this creates an authorization gap: the runtime or reviewer cannot clearly constrain what files may be read or what outbound requests are permitted, increasing the risk of unintended data exposure or misuse of network capabilities.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The document establishes a global rule at L044-L066 that all capabilities must first obtain explicit user answers and consent before continuing, especially before analysis or execution. L157 then directly contradicts that by stating Python/Node.js users can be given complete code examples '无需额外确认', which reverses the mandated confirmation flow for that capability.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The documentation shows HTTP requests to WeChat Pay and later posts openid, order details, and payment amounts from frontend to backend, but it does not disclose that user and transaction data will be transmitted to external services. For markdown files, user-facing warnings should mention network transmission of user data when privacy-relevant behavior is described.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This markdown file provides runnable sample code that loads a merchant private key from disk and shows API credential fields, but the surrounding documentation does not warn users that they must handle these secrets securely and avoid exposing real credentials in source control or logs. Because this is a markdown file, SQP-2 applies to missing warnings in the skill description about behaviors affecting privacy or system integrity.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Returning SUCCESS/200 on exceptions acknowledges the callback even when processing failed, preventing legitimate retries from WeChat. This can cause lost payment state transitions, unrecorded orders, inconsistent ledgers, or missed fulfillment recovery, especially when errors occur after decryption or during business processing.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The refund callback handler also returns SUCCESS when an exception occurs, which suppresses legitimate retries and can hide failed refund-state updates. That can leave refund records inconsistent with WeChat's state, causing accounting discrepancies, customer support issues, or incorrect refund fulfillment logic.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file includes front-end code that creates an order and calls wx.requestPayment, which can trigger a real financial transaction. The surrounding documentation explains how to perform the payment flow but does not include any warning to users or implementers about ensuring explicit user consent and verifying amounts before initiating payment.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This document presents runnable refund code without a prominent warning that it performs real refund operations against the live WeChat Pay API when configured with production credentials. In a payment integration skill, that omission increases the risk of accidental execution causing real financial transactions, especially because the examples look copy-paste ready.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The sample passes result.refundId into queryRefund, but queryRefund constructs the endpoint for querying by outRefundNo, not refund_id. This mismatch can cause status checks to fail or query the wrong identifier, leading developers to mis-handle refund state and potentially issue unnecessary retries or inconsistent business actions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The route example contradicts the documented idempotency requirement by always generating a fresh outRefundNo from the order number and current timestamp. On retry after a timeout or ambiguous failure, this can submit a second distinct refund request instead of safely reusing the original refund identifier, creating duplicate or unintended refunds.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This markdown file embeds code that performs HTTP requests to an external payment endpoint and sends order details plus the user's openid. While the document explains how to use the API, it does not explicitly warn readers that running the sample will transmit payment-related and user-linked data to a third-party service.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · references/代码示例/Python/回调处理/回调处理.md (reported line 39)May include surrounding context.

md
self.appid = appid
        self.api_v3_key = api_v3_key
        # 微信支付平台证书下载URL
        self.platform_cert_url = "https://api.mch.weixin.qq.com/v3/certificates"
    
    def _get_platform_public_key(self, serial_no):
        """

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code reads the callback amount and directly processes the order without comparing it to the locally stored order amount and currency. If an attacker can trigger processing for a valid but mismatched payment record, or if business logic errors occur, the system may mark orders as paid for the wrong amount, leading to financial loss or fulfillment of underpaid orders.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The example prints sensitive payment-related data including openid, session_key, order results, and client payment signature parameters without any warning against production logging. These values can leak through application logs, observability pipelines, or shared debugging output and may expose user identifiers, session material, and payment metadata that should be tightly controlled.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The entire skill documentation and embedded examples are presented only in Chinese, including headings, comments, and usage guidance, with no indication that the skill is region-specific or that users may choose another language. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

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 · references/代码示例/Python/APP支付/APP支付.md (reported line 79)May include surrounding context.

md
"Content-Type": "application/json"
        }
        
        resp = requests.post(url, headers=headers, json=body)
        return resp.json()
    
    def refund(self, out_trade_no, out_refund_no, total_fee, refund_fee,

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 · references/代码示例/Python/JSAPI支付/JSAPI支付.md (reported line 91)May include surrounding context.

md
"Content-Type": "application/json"
        }
        
        resp = requests.post(url, headers=headers, json=body)
        return resp.json()
    
    def refund(self, out_trade_no, out_refund_no, total_fee, refund_fee,

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 · references/代码示例/Python/Native支付/Native支付.md (reported line 82)May include surrounding context.

md
"Content-Type": "application/json"
        }
        
        resp = requests.post(url, headers=headers, json=body)
        return resp.json()
    
    def refund(self, out_trade_no, out_refund_no, total_fee, refund_fee,

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 · references/代码示例/Python/小程序支付/小程序支付.md (reported line 82)May include surrounding context.

md
"Content-Type": "application/json"
        }
        
        resp = requests.post(url, headers=headers, json=body)
        return resp.json()
    
    def refund(self, out_trade_no, out_refund_no, total_fee, refund_fee,

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 · references/代码示例/Python/退款/退款.md (reported line 78)May include surrounding context.

md
"Content-Type": "application/json"
        }
        
        resp = requests.post(url, headers=headers, json=body)
        return resp.json()
    
    def refund(self, out_trade_no, out_refund_no, total_fee, refund_fee,

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · references/代码示例/Python/小程序支付/小程序支付.md (reported line 98)May include surrounding context.

换openid接口:

text
GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=CODE&grant_type=authorization_code

Q2: prepay_id过期了?