Skip to content

Commit 1406ac6

Browse files
committed
test: add host validation bypass prevention tests
1 parent a054974 commit 1406ac6

File tree

1 file changed

+99
-1
lines changed

1 file changed

+99
-1
lines changed

test/unit/socket-listeners.test.js

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,49 @@
11
import { describe, it, expect, vi, beforeEach } from 'vitest';
2-
import { initListeners, setNet } from '../../lib/socket-listeners.js';
2+
import { initListeners, setNet, isSameHost } from '../../lib/socket-listeners.js';
3+
4+
describe('isSameHost', () => {
5+
it('should match identical hostnames', () => {
6+
expect(isSameHost('example.com', 'example.com')).toBe(true);
7+
});
8+
9+
it('should be case insensitive', () => {
10+
expect(isSameHost('Example.COM', 'example.com')).toBe(true);
11+
expect(isSameHost('LOCALHOST', 'localhost')).toBe(true);
12+
});
13+
14+
it('should handle trailing dots (DNS root)', () => {
15+
expect(isSameHost('example.com.', 'example.com')).toBe(true);
16+
expect(isSameHost('example.com', 'example.com.')).toBe(true);
17+
});
18+
19+
it('should match localhost aliases', () => {
20+
expect(isSameHost('localhost', '127.0.0.1')).toBe(true);
21+
expect(isSameHost('localhost', '::1')).toBe(true);
22+
expect(isSameHost('127.0.0.1', '::1')).toBe(true);
23+
expect(isSameHost('localhost', '0.0.0.0')).toBe(true);
24+
});
25+
26+
it('should handle IPv6 brackets', () => {
27+
expect(isSameHost('[::1]', '::1')).toBe(true);
28+
expect(isSameHost('[::1]', 'localhost')).toBe(true);
29+
});
30+
31+
it('should handle expanded IPv6 localhost', () => {
32+
expect(isSameHost('0:0:0:0:0:0:0:1', '::1')).toBe(true);
33+
expect(isSameHost('0:0:0:0:0:0:0:1', 'localhost')).toBe(true);
34+
});
35+
36+
it('should not match different hosts', () => {
37+
expect(isSameHost('example.com', 'other.com')).toBe(false);
38+
expect(isSameHost('localhost', 'example.com')).toBe(false);
39+
});
40+
41+
it('should handle empty/null inputs', () => {
42+
expect(isSameHost('', '')).toBe(true);
43+
expect(isSameHost('example.com', '')).toBe(false);
44+
expect(isSameHost('', 'example.com')).toBe(false);
45+
});
46+
});
347

448
describe('socket-listeners', () => {
549
let mockNet;
@@ -100,6 +144,60 @@ describe('socket-listeners', () => {
100144
).toThrow('targetHost must be a different host');
101145
});
102146

147+
it('should throw if targetHost matches client with different case', () => {
148+
expect(() =>
149+
listeners.addSocketListener({
150+
port: 3000,
151+
targetHost: 'https://LOCAL.EXAMPLE.COM',
152+
})
153+
).toThrow('targetHost must be a different host');
154+
});
155+
156+
it('should throw if targetHost matches client with trailing dot', () => {
157+
expect(() =>
158+
listeners.addSocketListener({
159+
port: 3000,
160+
targetHost: 'https://local.example.com.',
161+
})
162+
).toThrow('targetHost must be a different host');
163+
});
164+
165+
it('should block localhost bypass via 127.0.0.1', () => {
166+
mockHsyncClient.myHostName = 'localhost';
167+
listeners = initListeners(mockHsyncClient);
168+
169+
expect(() =>
170+
listeners.addSocketListener({
171+
port: 3000,
172+
targetHost: 'https://127.0.0.1',
173+
})
174+
).toThrow('targetHost must be a different host');
175+
});
176+
177+
it('should block localhost bypass via IPv6 ::1', () => {
178+
mockHsyncClient.myHostName = 'localhost';
179+
listeners = initListeners(mockHsyncClient);
180+
181+
expect(() =>
182+
listeners.addSocketListener({
183+
port: 3000,
184+
targetHost: 'https://[::1]',
185+
})
186+
).toThrow('targetHost must be a different host');
187+
});
188+
189+
it('should block localhost bypass via 0.0.0.0', () => {
190+
mockHsyncClient.myHostName = '127.0.0.1';
191+
listeners = initListeners(mockHsyncClient);
192+
193+
expect(() =>
194+
listeners.addSocketListener({
195+
port: 3000,
196+
targetHost: 'https://0.0.0.0',
197+
})
198+
).toThrow('targetHost must be a different host');
199+
});
200+
103201
it('should clean trailing slash from targetHost', () => {
104202
const listener = listeners.addSocketListener({
105203
port: 3000,

0 commit comments

Comments
 (0)