Skip to content

Commit 243a06e

Browse files
committed
test(security): use real isPrivateOrReservedIP and cover IPv6 edge cases
1 parent 5d4563a commit 243a06e

1 file changed

Lines changed: 8 additions & 16 deletions

File tree

apps/sim/app/api/tools/onepassword/utils.test.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
/**
22
* @vitest-environment node
33
*/
4-
import { inputValidationMock, inputValidationMockFns } from '@sim/testing'
54
import { beforeEach, describe, expect, it, vi } from 'vitest'
65

76
const { mockDnsLookup, hostedFlag } = vi.hoisted(() => ({
@@ -15,31 +14,16 @@ vi.mock('@/lib/core/config/feature-flags', () => ({
1514
},
1615
}))
1716

18-
vi.mock('@/lib/core/security/input-validation.server', () => inputValidationMock)
19-
2017
vi.mock('dns/promises', () => ({
2118
default: { lookup: mockDnsLookup },
2219
}))
2320

2421
import { validateConnectServerUrl } from '@/app/api/tools/onepassword/utils'
2522

26-
/** Mirrors the real isPrivateOrReservedIP for the ranges exercised here. */
27-
function fakeIsPrivateOrReservedIP(ip: string): boolean {
28-
if (ip.startsWith('10.') || ip.startsWith('192.168.')) return true
29-
if (ip.startsWith('172.')) {
30-
const second = Number.parseInt(ip.split('.')[1], 10)
31-
if (second >= 16 && second <= 31) return true
32-
}
33-
if (ip.startsWith('169.254.')) return true
34-
if (ip.startsWith('127.') || ip === '::1') return true
35-
return false
36-
}
37-
3823
describe('validateConnectServerUrl', () => {
3924
beforeEach(() => {
4025
vi.clearAllMocks()
4126
hostedFlag.value = false
42-
inputValidationMockFns.mockIsPrivateOrReservedIP.mockImplementation(fakeIsPrivateOrReservedIP)
4327
})
4428

4529
it('rejects a non-URL string', async () => {
@@ -57,6 +41,8 @@ describe('validateConnectServerUrl', () => {
5741
['RFC1918 192.168.x', 'http://192.168.1.1:8443'],
5842
['RFC1918 172.16.x', 'http://172.16.0.9'],
5943
['link-local metadata', 'http://169.254.169.254'],
44+
['IPv4-mapped IPv6 private', 'http://[::ffff:10.0.0.1]'],
45+
['IPv6 loopback', 'http://[::1]'],
6046
])('blocks %s', async (_label, url) => {
6147
await expect(validateConnectServerUrl(url)).rejects.toThrow(
6248
'cannot point to a private or reserved IP address'
@@ -101,6 +87,12 @@ describe('validateConnectServerUrl', () => {
10187
)
10288
})
10389

90+
it('still blocks IPv6 link-local', async () => {
91+
await expect(validateConnectServerUrl('http://[fe80::1]')).rejects.toThrow(
92+
'cannot point to a link-local address'
93+
)
94+
})
95+
10496
it('allows a hostname that resolves to a private IP', async () => {
10597
mockDnsLookup.mockResolvedValue({ address: '10.1.2.3', family: 4 })
10698
await expect(validateConnectServerUrl('https://connect.internal')).resolves.toBe('10.1.2.3')

0 commit comments

Comments
 (0)