SPB Git
2.3 KB · 32 lines typescript
1import { describe, it, expect } from "vitest";2import { normalizeUrl, isPrivateIp, extractHtmlMeta, sameSite, assertPublicHost } from "@/lib/url";3describe("normalizeUrl", () => {4  it("lower-cases host, strips trackers, fragment, default port and trailing slash", () => {5    expect(normalizeUrl("HTTPS://WWW.Example.com:443/Docs/?utm_source=x&b=2&a=1#top")).toBe("https://www.example.com/Docs?a=1&b=2");6    expect(normalizeUrl("https://example.com/")).toBe("https://example.com/");7    expect(normalizeUrl("https://example.com/path/")).toBe("https://example.com/path");8  });9  it("removes credentials and rejects non-http schemes", () => {10    expect(normalizeUrl("https://user:pw@example.com/x")).toBe("https://example.com/x");11    expect(() => normalizeUrl("javascript:alert(1)")).toThrow();12    expect(() => normalizeUrl("file:///etc/passwd")).toThrow();13  });14  it("sameSite ignores www", () => { expect(sameSite("https://www.a.com/x", "https://a.com/y")).toBe(true); expect(sameSite("https://a.com", "https://b.com")).toBe(false); });15});16describe("SSRF guard", () => {17  it("flags private, loopback, link-local, CGNAT and metadata ranges", () => {18    for (const ip of ["10.0.0.1", "127.0.0.1", "169.254.169.254", "172.16.5.5", "172.31.255.255", "192.168.2.80", "100.64.0.1", "100.127.255.255", "0.0.0.0", "224.0.0.1", "::1", "fd00::1", "fe80::1", "::ffff:10.0.0.1"]) expect(isPrivateIp(ip), ip).toBe(true);19    for (const ip of ["8.8.8.8", "1.1.1.1", "172.32.0.1", "100.128.0.1", "2606:4700::1111"]) expect(isPrivateIp(ip), ip).toBe(false);20  });21  it("rejects blocked hostnames before DNS", async () => {22    for (const h of ["localhost", "m3u96a.maclustr.io", "foo.local", "metadata.google.internal", "169.254.169.254", "10.67.0.1", "intranet"]) await expect(assertPublicHost(h), h).rejects.toThrow();23  });24});25describe("extractHtmlMeta", () => {26  it("reads title, canonical and description and decodes entities", () => {27    const m = extractHtmlMeta(`<html><head><title> A &amp; B </title><link rel="canonical" href="https://x.com/a"><meta name="description" content="Desc &quot;q&quot;"></head></html>`);28    expect(m).toEqual({ title: "A & B", canonical: "https://x.com/a", description: 'Desc "q"' });29  });30  it("tolerates missing tags", () => { expect(extractHtmlMeta("<p>hi</p>")).toEqual({ title: null, canonical: null, description: null }); });31});32
Files · 19c0ff748ee94e0979c734f5fb3afeefc11ee9e1
Menu

Theme