webhooks.test.js
1.38 KB
import { createHmac } from 'node:crypto'
import { describe, expect, it } from 'vitest'
import { isPublicAddress, signWebhook } from '../src/webhooks.js'
describe('Webhook 签名', () => {
it('sha256=HMAC(secret, timestamp + "." + body),接收方用同一 secret 可验证', () => {
const body = '{"id":"42","type":"task.accepted"}'
const signature = signWebhook('s3cret', '1791600000', body)
expect(signature).toBe(`sha256=${createHmac('sha256', 's3cret').update(`1791600000.${body}`).digest('hex')}`)
expect(signature).toMatch(/^sha256=[0-9a-f]{64}$/)
expect(signWebhook('s3cret', '1791600001', body)).not.toBe(signature)
expect(signWebhook('other', '1791600000', body)).not.toBe(signature)
})
})
describe('Webhook 目标地址(防 SSRF)', () => {
it.each(['127.0.0.1', '10.1.2.3', '172.16.0.1', '172.31.255.255', '192.168.1.1', '169.254.169.254', '100.64.0.1', '0.0.0.0', '224.0.0.1', '::1', '::', 'fe80::1', 'fc00::1', 'fd12:3456::1', '::ffff:127.0.0.1', '::ffff:10.0.0.1'])('%s 不是公网地址', (address) => {
expect(isPublicAddress(address)).toBe(false)
})
it.each(['8.8.8.8', '1.1.1.1', '172.32.0.1', '93.184.216.34', '2606:4700:4700::1111'])('%s 是公网地址', (address) => {
expect(isPublicAddress(address)).toBe(true)
})
it('不是 IP 直接 throw', () => {
expect(() => isPublicAddress('example.com')).toThrow(/not an IP address/)
})
})