mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
fix(metrics): reject non-loopback callers on metrics endpoints (#2222)
This commit is contained in:
1 parent
0a920def2b
commit
50a17b6263
6 files changed
+231
-22
No files matched your search
@@ -316,6 +316,30 @@ export function isPublicIpAddress(ip: string): boolean {
|
||||
return isPublicIpv6Address(parsed.normalized);
|
||||
}
|
||||
|
||||
function isLoopbackIpv4Address(address: string): boolean {
|
||||
const octets = parseIpv4Octets(address);
|
||||
if (!octets) {
|
||||
return false;
|
||||
}
|
||||
return isIpv4InCidr(octets, 0x7f000000, 8);
|
||||
}
|
||||
|
||||
export function isLoopbackIpAddress(ip: string): boolean {
|
||||
const parsed = parseIpAddress(ip);
|
||||
if (!parsed) {
|
||||
return false;
|
||||
}
|
||||
if (parsed.family === 'ipv4') {
|
||||
return isLoopbackIpv4Address(parsed.normalized);
|
||||
}
|
||||
const mappedIpv4 = getIpv4MappedIpv6(parsed.normalized);
|
||||
if (mappedIpv4) {
|
||||
return isLoopbackIpv4Address(mappedIpv4);
|
||||
}
|
||||
const groups = expandIpv6ToGroups(parsed.normalized);
|
||||
return groups.length === 8 && groups.slice(0, 7).every((group) => group === '0000') && groups[7] === '0001';
|
||||
}
|
||||
|
||||
export function isSameIpDecisionMatch(left: string | null | undefined, right: string | null | undefined): boolean {
|
||||
if (!left || !right) {
|
||||
return false;
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
getIpNetworkKey,
|
||||
getSameIpDecisionKey,
|
||||
getSubnet,
|
||||
isLoopbackIpAddress,
|
||||
isPublicIpAddress,
|
||||
isSameIpDecisionMatch,
|
||||
isValidIp,
|
||||
@@ -119,6 +120,36 @@ describe('maskIpForDisplay', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isLoopbackIpAddress', () => {
|
||||
it('accepts IPv4 loopback addresses', () => {
|
||||
expect(isLoopbackIpAddress('127.0.0.1')).toBe(true);
|
||||
expect(isLoopbackIpAddress('127.0.0.2')).toBe(true);
|
||||
expect(isLoopbackIpAddress('127.255.255.254')).toBe(true);
|
||||
});
|
||||
it('accepts IPv6 loopback and its IPv4-mapped form', () => {
|
||||
expect(isLoopbackIpAddress('::1')).toBe(true);
|
||||
expect(isLoopbackIpAddress('[::1]')).toBe(true);
|
||||
expect(isLoopbackIpAddress('0:0:0:0:0:0:0:1')).toBe(true);
|
||||
expect(isLoopbackIpAddress('::ffff:127.0.0.1')).toBe(true);
|
||||
expect(isLoopbackIpAddress('::ffff:7f00:1')).toBe(true);
|
||||
});
|
||||
it('rejects non-loopback addresses', () => {
|
||||
expect(isLoopbackIpAddress('8.8.8.8')).toBe(false);
|
||||
expect(isLoopbackIpAddress('10.0.0.5')).toBe(false);
|
||||
expect(isLoopbackIpAddress('172.18.0.4')).toBe(false);
|
||||
expect(isLoopbackIpAddress('192.168.1.1')).toBe(false);
|
||||
expect(isLoopbackIpAddress('128.0.0.1')).toBe(false);
|
||||
expect(isLoopbackIpAddress('126.255.255.255')).toBe(false);
|
||||
expect(isLoopbackIpAddress('::2')).toBe(false);
|
||||
expect(isLoopbackIpAddress('fe80::1')).toBe(false);
|
||||
expect(isLoopbackIpAddress('::ffff:8.8.8.8')).toBe(false);
|
||||
});
|
||||
it('rejects invalid values', () => {
|
||||
expect(isLoopbackIpAddress('not-an-ip')).toBe(false);
|
||||
expect(isLoopbackIpAddress('')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isPublicIpAddress', () => {
|
||||
it('accepts public unicast addresses', () => {
|
||||
expect(isPublicIpAddress('8.8.8.8')).toBe(true);
|
||||
|
||||
Reference in new issue
Block a user