Block hex-mapped IPv6 invite probes

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-04-20 10:46:50 -05:00
1 parent 078094e1e9
commit eb3503a266
2 files changed
+18 -2

No files matched your search

@@ -87,6 +87,8 @@ describe("GET /invites/:token/test-resolution", () => {
["localhost", "http://localhost:3100/api/health", "127.0.0.1"],
["IPv4 loopback", "http://127.0.0.1:3100/api/health", "127.0.0.1"],
["IPv6 loopback", "http://[::1]:3100/api/health", "::1"],
["IPv4-mapped IPv6 loopback hex", "http://[::ffff:7f00:1]/api/health", "::ffff:7f00:1"],
["IPv4-mapped IPv6 RFC1918 hex", "http://[::ffff:c0a8:101]/api/health", "::ffff:c0a8:101"],
["RFC1918 10/8", "http://10.0.0.5/api/health", "10.0.0.5"],
["RFC1918 172.16/12", "http://172.16.10.5/api/health", "172.16.10.5"],
["RFC1918 192.168/16", "http://192.168.1.10/api/health", "192.168.1.10"],
+16 -2
View File
@@ -2166,10 +2166,24 @@ function isPrivateOrReservedIpv4(address: string) {
return false;
}
function parseMappedIpv4Hex(address: string) {
const match = address.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);
if (!match) return null;
const hi = Number.parseInt(match[1]!, 16);
const lo = Number.parseInt(match[2]!, 16);
if (!Number.isInteger(hi) || !Number.isInteger(lo)) return null;
return `${hi >> 8}.${hi & 0xff}.${lo >> 8}.${lo & 0xff}`;
}
function isPrivateOrReservedIpv6(address: string) {
const lower = address.toLowerCase();
const mappedIpv4 = lower.match(/^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/);
if (mappedIpv4?.[1]) return isPrivateOrReservedIpv4(mappedIpv4[1]);
if (lower.startsWith("::ffff:")) {
const mappedIpv4 = lower.match(/^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/);
if (mappedIpv4?.[1]) return isPrivateOrReservedIpv4(mappedIpv4[1]);
const mappedIpv4Hex = parseMappedIpv4Hex(lower);
if (mappedIpv4Hex) return isPrivateOrReservedIpv4(mappedIpv4Hex);
return true;
}
if (lower === "::" || lower === "::1") return true;
if (lower.startsWith("fc") || lower.startsWith("fd")) return true;
if (/^fe[89ab]/.test(lower)) return true;