T09 · Insecure Skill Coding Practices
- Location
SKILL.md:94- Finding
WeChat Pay callback headers are collected but never cryptographically verified
- Content
View full analysis
{ try { // Step 1: Verify signature const signature = req.headers['wechatpay-signature']; const timestamp = req.headers['wechatpay-timestamp']; const nonce = req.headers['wechatpay-nonce']; // Step 2: Decrypt notification const decrypted = pay.decipher_gcm( req.body.resource.ciphertext, req.body.resource.associated_data, req.body.resource.nonce, ); ``` ### Technical Analysis The handler reads the `Wechatpay-Signature`, `Wechatpay-Timestamp`, and `Wechatpay-Nonce` headers, but it never uses them to verify the HTTP notification signature with the WeChat Pay platform certificate. The comment claiming that signature verification occurs is therefore inaccurate. Authenticated decryption of the `resource` object protects the encrypted resource, but it does not replace verification of the complete callback envelope. The handler also does not enforce timestamp freshness or detect repeated notification identifiers. Applications copied from this example may consequently lack the callback authenticity and replay controls required by the WeChat Pay protocol. Signature verification must use the exact raw HTTP request body. Verifying a parsed and reserialized JSON object can fail because its byte representation may differ from the signed payload. ### Attack Path 1. An attacker captures or otherwise obtains a legitimate callback request sent to the merchant endpoint. 2. The attacker replays the callback, potentially with unverified envelope metadata. 3. The endpoint extracts the signature-related headers but performs no cryptographic verification or timestamp freshness check. 4. If the encrypted resource remains valid, the handler decrypts it and proceeds to payment ...[truncated 549 chars]- Remediation
View remediation
