11/**
22 * @vitest -environment node
33 */
4- import { inputValidationMock , inputValidationMockFns } from '@sim/testing'
54import { beforeEach , describe , expect , it , vi } from 'vitest'
65
76const { 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-
2017vi . mock ( 'dns/promises' , ( ) => ( {
2118 default : { lookup : mockDnsLookup } ,
2219} ) )
2320
2421import { 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-
3823describe ( '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