release: v1.2.2 — 双域名配置与 Host 隔离修复
GitHub Release / release (push) Canceled after 0s
Publish Docker image / build (linux/amd64, ubuntu-latest, amd64) (push) Canceled after 0s
Publish Docker image / build (linux/arm64, ubuntu-24.04-arm, arm64) (push) Canceled after 0s
Publish Docker image / merge (push) Canceled after 0s
ci / ci (22, ubuntu-latest) (push) Canceled after 0s

修复设置页误清空管理域、配置与生效 URL 混淆及第三 Host 绕过隔离;加固 Settings API 与中间件,并更新文档站。
This commit is contained in:
O96u committed 2026-08-30 10:57:26 +08:00
1 parent 6c6766221b
commit c9c34515dd
36 files changed
+2578 -180

No files matched your search

+48 -16
View File
@@ -8,6 +8,20 @@ import {
} from './env'
import { requestPathToImageKey } from './serve-image'
const DEV_LOCAL_HOSTS = new Set(['localhost', '127.0.0.1'])
function getIsolationRequestHost(event: H3Event): string {
const requestUrl = getRequestURL(event, {
xForwardedHost: true,
xForwardedProto: true
})
return requestUrl.hostname.toLowerCase()
}
function isDevLocalHost(host: string): boolean {
return process.env.NODE_ENV === 'development' && DEV_LOCAL_HOSTS.has(host)
}
export function getConfiguredSiteHost(event: H3Event): string | null {
return hostnameFromBaseUrl(getSiteBaseUrlConfigured(event))
}
@@ -16,6 +30,30 @@ export function getConfiguredImageHost(event: H3Event): string | null {
return hostnameFromBaseUrl(getImageBaseUrlConfigured(event))
}
/** 双域名开启时,拒绝未配置的第三 Host(开发环境 localhost 例外) */
export function shouldBlockUnknownHostRequest(
event: H3Event,
options?: {
requestHost?: string
separationActive?: boolean
siteHost?: string | null
imageHost?: string | null
}
): boolean {
const separationActive = options?.separationActive ?? isDomainSeparationActive(event)
if (!separationActive) return false
const siteHost = options?.siteHost ?? getConfiguredSiteHost(event)
const imageHost = options?.imageHost ?? getConfiguredImageHost(event)
if (!siteHost || !imageHost) return false
const requestHost = (options?.requestHost ?? getIsolationRequestHost(event)).toLowerCase()
if (requestHost === siteHost || requestHost === imageHost) return false
if (isDevLocalHost(requestHost)) return false
return true
}
export function shouldBlockImageHostRequest(
event: H3Event,
options?: {
@@ -34,19 +72,16 @@ export function shouldBlockImageHostRequest(
const imageHost = options?.imageHost ?? getConfiguredImageHost(event)
if (!imageHost) return false
const requestUrl = options?.requestHost
? null
: getRequestURL(event, {
xForwardedHost: true,
xForwardedProto: true
})
const requestHost = (options?.requestHost ?? requestUrl?.hostname ?? '').toLowerCase()
const requestHost = (options?.requestHost ?? getIsolationRequestHost(event)).toLowerCase()
if (requestHost !== imageHost) return false
const method = (options?.method ?? getMethod(event)).toUpperCase()
if (method !== 'GET' && method !== 'HEAD') return true
const pathname = options?.pathname ?? requestUrl?.pathname ?? ''
const pathname = options?.pathname ?? getRequestURL(event, {
xForwardedHost: true,
xForwardedProto: true
}).pathname
const hideFolder = options?.hideFolder ?? isHideFolderInUrl(event)
return requestPathToImageKey(pathname, {
hideFolder
@@ -71,19 +106,16 @@ export function shouldBlockSiteHostImageRequest(
const siteHost = options?.siteHost ?? getConfiguredSiteHost(event)
if (!siteHost) return false
const requestUrl = options?.requestHost
? null
: getRequestURL(event, {
xForwardedHost: true,
xForwardedProto: true
})
const requestHost = (options?.requestHost ?? requestUrl?.hostname ?? '').toLowerCase()
const requestHost = (options?.requestHost ?? getIsolationRequestHost(event)).toLowerCase()
if (requestHost !== siteHost) return false
const method = (options?.method ?? getMethod(event)).toUpperCase()
if (method !== 'GET' && method !== 'HEAD') return false
const pathname = options?.pathname ?? requestUrl?.pathname ?? ''
const pathname = options?.pathname ?? getRequestURL(event, {
xForwardedHost: true,
xForwardedProto: true
}).pathname
const hideFolder = options?.hideFolder ?? isHideFolderInUrl(event)
return requestPathToImageKey(pathname, {
hideFolder