Security Update

This commit is contained in:
2025-12-24 22:14:07 +08:00
parent bbaff73f9b
commit e66d7b31cf
2 changed files with 23 additions and 9 deletions

View File

@@ -626,7 +626,15 @@ export function makeRequest(request, data) {
const callbackRequest = `${request}_callback`; const callbackRequest = `${request}_callback`;
function handleMessage(event) { function handleMessage(event) {
// 安全修复:验证消息来源
if (event.origin !== window.location.origin && event.origin !== 'null') {
return;
}
const msgData = event.data || {}; const msgData = event.data || {};
// 安全修复:确保消息源是我们期望的
if (msgData.source !== 'amily2-iframe-request') return;
if (msgData.request === callbackRequest && msgData.uid === uid) { if (msgData.request === callbackRequest && msgData.uid === uid) {
window.removeEventListener('message', handleMessage); window.removeEventListener('message', handleMessage);
if (msgData.error) { if (msgData.error) {
@@ -649,7 +657,7 @@ export function makeRequest(request, data) {
request: request, request: request,
uid: uid, uid: uid,
data: data data: data
}, '*'); }, window.location.origin);
}); });
} }
@@ -668,6 +676,12 @@ export function registerApiHandler(request, handler) {
export function initializeApiListener() { export function initializeApiListener() {
window.addEventListener('message', async (event) => { window.addEventListener('message', async (event) => {
// 安全修复:严格验证消息来源,防止跨源消息伪造
// 'null' 是 srcdoc 或 blob URL iframe 的 origin
if (event.origin !== window.location.origin && event.origin !== 'null') {
return;
}
const data = event.data || {}; const data = event.data || {};
if (data.source !== 'amily2-iframe-request' || !data.request || data.uid === undefined) { if (data.source !== 'amily2-iframe-request' || !data.request || data.uid === undefined) {
return; return;
@@ -682,7 +696,7 @@ export function initializeApiListener() {
request: callbackRequest, request: callbackRequest,
uid: data.uid, uid: data.uid,
error: `未注册请求 '${data.request}' 的处理器` error: `未注册请求 '${data.request}' 的处理器`
}, '*'); }, event.origin); // 安全修复:回复到确切的来源,而不是 '*'
return; return;
} }
@@ -692,14 +706,14 @@ export function initializeApiListener() {
request: callbackRequest, request: callbackRequest,
uid: data.uid, uid: data.uid,
result: result result: result
}, '*'); }, event.origin); // 安全修复:回复到确切的来源
} catch (error) { } catch (error) {
console.error(`[Amily2-IframeAPI] 执行处理器 '${data.request}' 时出错:`, error); console.error(`[Amily2-IframeAPI] 执行处理器 '${data.request}' 时出错:`, error);
event.source.postMessage({ event.source.postMessage({
request: callbackRequest, request: callbackRequest,
uid: data.uid, uid: data.uid,
error: error.message || String(error) error: error.message || String(error)
}, '*'); }, event.origin); // 安全修复:回复到确切的来源
} }
}); });
console.log('[Amily2-IframeAPI] 主窗口监听器已初始化'); console.log('[Amily2-IframeAPI] 主窗口监听器已初始化');

View File

@@ -565,11 +565,11 @@ function renderHtmlInIframe(htmlContent, container, preElement) {
iframe.setAttribute('frameborder', '0'); iframe.setAttribute('frameborder', '0');
iframe.setAttribute('scrolling', 'no'); iframe.setAttribute('scrolling', 'no');
iframe.loading = 'eager'; iframe.loading = 'eager';
if (settings.sandboxMode) { // 始终使用严格的沙箱策略,移除 allow-same-origin 以防止XSS攻击。
iframe.setAttribute('sandbox', 'allow-scripts allow-modals'); // 仅允许脚本、表单、弹窗和模态框。
} else { // allow-popups-to-escape-sandbox 允许弹窗(如新标签页)摆脱沙箱限制,这对于外部链接是必要的。
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-modals allow-popups'); // allow-downloads 允许文件下载。
} iframe.setAttribute('sandbox', 'allow-scripts allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-downloads');
if (needsVh) { if (needsVh) {
iframe.dataset.needsVh = 'true'; iframe.dataset.needsVh = 'true';