import { describe, expect, it } from
"vitest";
import { extractLinksFromMessage } from
"./detect.js";
describe(
"extractLinksFromMessage", () => {
it(
"extracts bare http/https URLs in order", () => {
const links = extractLinksFromMessage(
"see https://a.example and http://b.test");
expect(links).toEqual([
"https://a.example", "http://b.test"]);
});
it(
"dedupes links and enforces maxLinks", () => {
const links = extractLinksFromMessage(
"https://a.example https://a.example https://b.test", {
maxLinks:
1,
});
expect(links).toEqual([
"https://a.example"]);
});
it(
"ignores markdown links", () => {
const links = extractLinksFromMessage(
"[doc](https://docs.example) https://bare.example");
expect(links).toEqual([
"https://bare.example"]);
});
it(
"blocks 127.0.0.1", () => {
const links = extractLinksFromMessage(
"http://127.0.0.1/test https://ok.test");
expect(links).toEqual([
"https://ok.test"]);
});
it(
"blocks localhost and common loopback addresses", () => {
expect(extractLinksFromMessage(
"http://localhost/secret")).toEqual([]);
expect(extractLinksFromMessage(
"http://localhost.localdomain/secret")).toEqual([]);
expect(extractLinksFromMessage(
"http://foo.localhost/secret")).toEqual([]);
expect(extractLinksFromMessage(
"http://service.local/secret")).toEqual([]);
expect(extractLinksFromMessage(
"http://service.internal/secret")).toEqual([]);
expect(extractLinksFromMessage(
"http://0.0.0.0/secret")).toEqual([]);
expect(extractLinksFromMessage(
"http://[::1]/secret")).toEqual([]);
});
it(
"blocks private network ranges", () => {
expect(extractLinksFromMessage(
"http://10.0.0.1/internal")).toEqual([]);
expect(extractLinksFromMessage(
"http://172.16.0.1/internal")).toEqual([]);
expect(extractLinksFromMessage(
"http://192.168.1.1/internal")).toEqual([]);
});
it(
"blocks link-local and cloud metadata addresses", () => {
expect(extractLinksFromMessage(
"http://169.254.169.254/latest/meta-data/")).toEqual([]);
expect(extractLinksFromMessage(
"http://169.254.1.1/test")).toEqual([]);
expect(extractLinksFromMessage(
"http://metadata.google.internal/computeMetadata/v1/")).toEqual(
[],
);
});
it(
"blocks CGNAT range used by Tailscale", () => {
expect(extractLinksFromMessage(
"http://100.100.50.1/test")).toEqual([]);
});
it(
"blocks private and mapped IPv6 addresses", () => {
expect(extractLinksFromMessage(
"http://[::ffff:127.0.0.1]/secret")).toEqual([]);
expect(extractLinksFromMessage(
"http://[2001:db8:1234::5efe:127.0.0.1]/secret")).toEqual([]);
expect(extractLinksFromMessage(
"http://[fe80::1]/secret")).toEqual([]);
expect(extractLinksFromMessage(
"http://[fc00::1]/secret")).toEqual([]);
});
it(
"allows legitimate public URLs", () => {
expect(extractLinksFromMessage(
"https://example.com/page")).toEqual([
"https://example.com/page",
]);
expect(extractLinksFromMessage(
"https://8.8.8.8/dns")).toEqual(["https://8.8.8.8/dns"]);
});
});