fix(h5): prevent internal asset host exposure
Some checks failed
CI / verify (push) Has been cancelled

Made-with: Proma
This commit is contained in:
cxk
2026-08-15 19:01:55 +08:00
parent 2edb6bd9f2
commit 00585a7b48
5 changed files with 19 additions and 31 deletions

View File

@@ -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
]

View File

@@ -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'

2
src/env.d.ts vendored
View File

@@ -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 {

View File

@@ -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}`

View File

@@ -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')