补强静态发布安全边界
This commit is contained in:
62
electron/api/works-play-url.ts
Normal file
62
electron/api/works-play-url.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
const MAX_WORKS_PLAY_URL_LENGTH = 1_024;
|
||||
|
||||
function isLoopbackHostname(hostname: string): boolean {
|
||||
const normalized = hostname.toLowerCase().replace(/^\[|\]$/g, '');
|
||||
return normalized === 'localhost'
|
||||
|| normalized.endsWith('.localhost')
|
||||
|| normalized === '::'
|
||||
|| normalized === '::1'
|
||||
|| normalized.startsWith('::ffff:127.')
|
||||
|| normalized.startsWith('::ffff:7f00:')
|
||||
|| normalized === '0.0.0.0'
|
||||
|| normalized.startsWith('127.');
|
||||
}
|
||||
|
||||
function trustedWorksHttpsUrl(value: string, worksBase: URL): URL | null {
|
||||
try {
|
||||
const target = new URL(value, worksBase);
|
||||
if (
|
||||
target.toString().length > MAX_WORKS_PLAY_URL_LENGTH
|
||||
|| worksBase.protocol !== 'https:'
|
||||
|| target.protocol !== 'https:'
|
||||
|| target.origin !== worksBase.origin
|
||||
|| Boolean(target.username || target.password)
|
||||
|| isLoopbackHostname(target.hostname)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return target;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function trustedWorksProjectPlayUrl(
|
||||
value: string,
|
||||
worksBase: URL,
|
||||
appId: string,
|
||||
): string | null {
|
||||
const normalizedAppId = appId.trim();
|
||||
if (!normalizedAppId) return null;
|
||||
const target = trustedWorksHttpsUrl(value, worksBase);
|
||||
if (
|
||||
!target
|
||||
|| target.pathname !== `/apps/${encodeURIComponent(normalizedAppId)}/`
|
||||
|| target.search
|
||||
|| target.hash
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return target.toString();
|
||||
}
|
||||
|
||||
export function trustedWorksReleasePreviewUrl(
|
||||
value: string,
|
||||
worksBase: URL,
|
||||
releaseId: string,
|
||||
): string | null {
|
||||
const target = trustedWorksHttpsUrl(value, worksBase);
|
||||
if (!target) return null;
|
||||
const expectedPrefix = `/previews/${encodeURIComponent(releaseId)}/`;
|
||||
return target.pathname.startsWith(expectedPrefix) ? target.toString() : null;
|
||||
}
|
||||
Reference in New Issue
Block a user