Handle invalid IPs and localhost lookup failures in location detection
This commit is contained in:
1 parent
fa4318fb87
commit
f69f76b3b1
2 files changed
+65
-2
No files matched your search
+56
-1
@@ -1,8 +1,23 @@
|
||||
import { expect, test } from 'vitest';
|
||||
import { beforeEach, expect, test, vi } from 'vitest';
|
||||
import { getLocation, hasBlockedIp } from './detect';
|
||||
import { getIpAddress } from './ip';
|
||||
|
||||
const IP = '127.0.0.1';
|
||||
|
||||
const isLocalhost = vi.mocked(await import('is-localhost-ip'));
|
||||
|
||||
vi.mock('is-localhost-ip', () => ({
|
||||
default: vi.fn(),
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
|
||||
delete process.env.CLIENT_IP_HEADER;
|
||||
delete process.env.IGNORE_IP;
|
||||
delete process.env.SKIP_LOCATION_HEADERS;
|
||||
});
|
||||
|
||||
test('getIpAddress: Custom header', () => {
|
||||
process.env.CLIENT_IP_HEADER = 'x-custom-ip-header';
|
||||
|
||||
@@ -20,3 +35,43 @@ test('getIpAddress: Standard header', () => {
|
||||
test('getIpAddress: No header', () => {
|
||||
expect(getIpAddress(new Headers())).toEqual(undefined);
|
||||
});
|
||||
|
||||
test('getLocation: returns null for malformed ip', async () => {
|
||||
await expect(
|
||||
getLocation(
|
||||
'not-an-ip',
|
||||
new Headers({
|
||||
'cf-ipcountry': 'US',
|
||||
'cf-region-code': 'CA',
|
||||
'cf-ipcity': 'Los Angeles',
|
||||
}),
|
||||
false,
|
||||
),
|
||||
).resolves.toEqual(null);
|
||||
});
|
||||
|
||||
test('getLocation: treats localhost check errors as non-local', async () => {
|
||||
isLocalhost.default.mockRejectedValue(new Error('DNS Lookup failed.'));
|
||||
|
||||
await expect(
|
||||
getLocation(
|
||||
'8.8.8.8',
|
||||
new Headers({
|
||||
'cf-ipcountry': 'US',
|
||||
'cf-region-code': 'CA',
|
||||
'cf-ipcity': 'Los Angeles',
|
||||
}),
|
||||
false,
|
||||
),
|
||||
).resolves.toEqual({
|
||||
country: 'US',
|
||||
region: 'US-CA',
|
||||
city: 'Los Angeles',
|
||||
});
|
||||
});
|
||||
|
||||
test('hasBlockedIp: returns false for malformed client ip with cidr block', () => {
|
||||
process.env.IGNORE_IP = '10.0.0.0/8';
|
||||
|
||||
expect(hasBlockedIp('not-an-ip')).toBe(false);
|
||||
});
|
||||
+9
-1
@@ -76,11 +76,19 @@ function decodeHeader(s: string | undefined | null): string | undefined | null {
|
||||
return Buffer.from(s, 'latin1').toString('utf-8');
|
||||
}
|
||||
|
||||
async function isLocalIp(ip: string) {
|
||||
try {
|
||||
return await isLocalhost(ip);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getLocation(ip: string = '', headers: Headers, skipHeaders: boolean) {
|
||||
const cleanIp = stripPort(ip);
|
||||
|
||||
// Ignore local or invalid ips
|
||||
if (!cleanIp || !ipaddr.isValid(cleanIp) || (await isLocalhost(cleanIp))) {
|
||||
if (!cleanIp || !ipaddr.isValid(cleanIp) || (await isLocalIp(cleanIp))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user