From 8785e63ead166089c679a9993653a02789b9d694 Mon Sep 17 00:00:00 2001 From: lizhe Date: Fri, 7 Aug 2026 18:08:42 +0800 Subject: [PATCH] fix(web): match IPv6 loopback hostname with brackets in isPrivateOrLocalAddress URL.hostname serializes IPv6 addresses with brackets (e.g. "[::1]"), but the localhost check compared against the unbracketed "::1", so it never matched and IPv6 loopback URLs weren't flagged as private/local. --- web/utils/urlValidation.spec.ts | 9 ++++++++- web/utils/urlValidation.ts | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/web/utils/urlValidation.spec.ts b/web/utils/urlValidation.spec.ts index 52163f2c682615..0be6be650adddc 100644 --- a/web/utils/urlValidation.spec.ts +++ b/web/utils/urlValidation.spec.ts @@ -1,4 +1,4 @@ -import { validateRedirectUrl } from './urlValidation' +import { isPrivateOrLocalAddress, validateRedirectUrl } from './urlValidation' describe('URL Validation', () => { describe('validateRedirectUrl', () => { @@ -56,4 +56,11 @@ describe('URL Validation', () => { expect(() => validateRedirectUrl('//example.com')).toThrow('Invalid URL') }) }) + + describe('isPrivateOrLocalAddress', () => { + it('should recognize the IPv6 loopback address', () => { + expect(isPrivateOrLocalAddress('http://[::1]/')).toBe(true) + expect(isPrivateOrLocalAddress('http://[::1]:8080/')).toBe(true) + }) + }) }) diff --git a/web/utils/urlValidation.ts b/web/utils/urlValidation.ts index 01ae0f70f1de10..a9e509433ead82 100644 --- a/web/utils/urlValidation.ts +++ b/web/utils/urlValidation.ts @@ -30,7 +30,7 @@ export function isPrivateOrLocalAddress(url: string): boolean { const hostname = urlObj.hostname.toLowerCase() // Check for localhost - if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1') return true + if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]') return true // Check for private IP ranges const ipv4Regex = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/