From 00585a7b48519ea463f85e66eea3107870ae23c6 Mon Sep 17 00:00:00 2001 From: cxk <119064883@qq.com> Date: Sat, 15 Aug 2026 19:01:55 +0800 Subject: [PATCH] fix(h5): prevent internal asset host exposure Made-with: Proma --- scripts/finalize-h5-build.cjs | 1 + src/config/dataSource.ts | 4 +--- src/env.d.ts | 2 -- src/utils/publicUrl.ts | 29 +++-------------------------- tests/unit/PublicUrl.spec.ts | 14 ++++++++++++++ 5 files changed, 19 insertions(+), 31 deletions(-) diff --git a/scripts/finalize-h5-build.cjs b/scripts/finalize-h5-build.cjs index b2fca7d..43ec7b3 100644 --- a/scripts/finalize-h5-build.cjs +++ b/scripts/finalize-h5-build.cjs @@ -10,6 +10,7 @@ const placeholder = '__REPLACE_WITH_TENCENT_MAP_WEB_KEY__' const badPatterns = [ 'http://1.92.206.90:9000', '1.92.206.90', + '172.20.14.21', 'guide.whaoyue.com', placeholder ] diff --git a/src/config/dataSource.ts b/src/config/dataSource.ts index 3f352f3..26d3cd6 100644 --- a/src/config/dataSource.ts +++ b/src/config/dataSource.ts @@ -100,9 +100,7 @@ export const dataSourceConfig = { audioApiTimeoutMs: normalizeTimeout( import.meta.env.VITE_AUDIO_API_TIMEOUT_MS || import.meta.env.VITE_EXPLAIN_API_TIMEOUT_MS, defaultExplainRequestTimeoutMs - ), - publicSameOriginAssetHost: import.meta.env.VITE_PUBLIC_SAME_ORIGIN_ASSET_HOST?.trim() || '', - publicLegacyAudioHost: import.meta.env.VITE_PUBLIC_LEGACY_AUDIO_HOST?.trim() || '' + ) } export const isSgsSdkMode = () => dataSourceConfig.guideDataMode === 'sdk' diff --git a/src/env.d.ts b/src/env.d.ts index 4d56781..718030e 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -25,8 +25,6 @@ interface ImportMetaEnv { readonly VITE_SGS_SDK_ORIGIN?: string readonly VITE_SGS_SDK_TIMEOUT_MS?: string readonly VITE_TENCENT_MAP_KEY?: string - readonly VITE_PUBLIC_SAME_ORIGIN_ASSET_HOST?: string - readonly VITE_PUBLIC_LEGACY_AUDIO_HOST?: string } interface ImportMeta { diff --git a/src/utils/publicUrl.ts b/src/utils/publicUrl.ts index 9b792ec..90fb80e 100644 --- a/src/utils/publicUrl.ts +++ b/src/utils/publicUrl.ts @@ -4,24 +4,6 @@ import { const isAbsoluteHttpUrl = (url: string) => /^https?:\/\//i.test(url) -const defaultSameOriginAssetHosts = [ - ['1', '92', '206', '90'].join('.') -] - -const defaultLegacyAudioHosts = [ - ['47', '120', '48', '148'].join('.') -] - -const configuredSameOriginAssetHosts = () => [ - dataSourceConfig.publicSameOriginAssetHost, - ...defaultSameOriginAssetHosts -].filter(Boolean) - -const configuredLegacyAudioHosts = () => [ - dataSourceConfig.publicLegacyAudioHost, - ...defaultLegacyAudioHosts -].filter(Boolean) - const resolveSdkMinioProxyBaseUrl = () => { const apiBaseUrl = dataSourceConfig.apiBaseUrl.trim().replace(/\/+$/, '') const normalizedApiBaseUrl = apiBaseUrl.endsWith('/app-api') @@ -50,11 +32,8 @@ export const normalizeSameOriginPublicUrl = (url: string | null | undefined) => try { const parsed = new URL(value) - const isSameServer = configuredSameOriginAssetHosts().includes(parsed.hostname) - if ( - isSameServer - && parsed.port === '9000' + parsed.port === '9000' && ( parsed.pathname.startsWith('/museum-assets/') || parsed.pathname.startsWith('/tts-audio/') @@ -64,16 +43,14 @@ export const normalizeSameOriginPublicUrl = (url: string | null | undefined) => } if ( - isSameServer - && parsed.port === '48080' + parsed.port === '48080' && parsed.pathname.startsWith('/yudao-server/') ) { return `${parsed.pathname}${parsed.search}${parsed.hash}` } if ( - configuredLegacyAudioHosts().includes(parsed.hostname) - && parsed.port === '19000' + parsed.port === '19000' && parsed.pathname.startsWith('/nhm/audio/') ) { return `${parsed.pathname}${parsed.search}${parsed.hash}` diff --git a/tests/unit/PublicUrl.spec.ts b/tests/unit/PublicUrl.spec.ts index 55ca93f..efc3909 100644 --- a/tests/unit/PublicUrl.spec.ts +++ b/tests/unit/PublicUrl.spec.ts @@ -12,6 +12,20 @@ describe('normalizeSameOriginPublicUrl', () => { )).toBe('/app-api/gis/sdk/minio/museum-assets/guide-final/E2/detail.jpg') }) + it('rewrites legacy absolute media and proxy URLs without embedding their host', () => { + expect(normalizeSameOriginPublicUrl( + 'http://172.20.14.21:9000/museum-assets/guide-final/E2/detail.jpg' + )).toBe('/app-api/gis/sdk/minio/museum-assets/guide-final/E2/detail.jpg') + + expect(normalizeSameOriginPublicUrl( + 'http://172.20.14.21:48080/yudao-server/app-api/gis/guide?stopId=1' + )).toBe('/yudao-server/app-api/gis/guide?stopId=1') + + expect(normalizeSameOriginPublicUrl( + 'http://172.20.14.21:19000/nhm/audio/guide.mp3' + )).toBe('/nhm/audio/guide.mp3') + }) + it('keeps ordinary relative paths unchanged', () => { expect(normalizeSameOriginPublicUrl('/static/placeholder.png')) .toBe('/static/placeholder.png')