fix(security): trust file: URLs only inside the app renderer directory

This commit is contained in:
Yun Chan 2026-09-28 02:16:18 +09:00
parent b306034bfc
commit 5322d981cc
5 changed files with 299 additions and 17 deletions

View file

@ -4,6 +4,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import { ipcMain, shell } from 'electron'
import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import {
appRendererFileRoot,
hardenWebContents,
isTrustedIpcSender,
openExternalSafe,
@ -50,7 +51,7 @@ describe('hardenWebContents', () => {
it('앱 자신의 페이지(file://)로의 이동은 허용한다', () => {
const w = fakeWindow()
hardenWebContents(w.win)
expect(w.fire('will-navigate', 'file:///C:/app/out/renderer/index.html#/x')).not.toHaveBeenCalled()
expect(w.fire('will-navigate', `${appRendererFileRoot()}index.html#/x`)).not.toHaveBeenCalled()
})
it('새 창은 항상 거부하고 file:/UNC/사용자 정의 scheme 은 OS로 넘기지 않는다', async () => {
@ -73,7 +74,7 @@ describe('openExternalSafe / isTrustedIpcSender', () => {
})
it('원격 페이지가 보낸 IPC 는 신뢰하지 않는다', () => {
expect(isTrustedIpcSender({ senderFrame: { url: 'file:///C:/app/index.html' } } as never)).toBe(true)
expect(isTrustedIpcSender({ senderFrame: { url: `${appRendererFileRoot()}index.html` } } as never)).toBe(true)
expect(isTrustedIpcSender({ senderFrame: { url: 'https://evil.example/' } } as never)).toBe(false)
expect(isTrustedIpcSender({ senderFrame: null } as never)).toBe(false)
})
@ -88,7 +89,7 @@ describe('SYSTEM.OPEN_EXTERNAL IPC', () => {
const { registerWindowHandlers } = await import('../../../src/main/ipc/window-handlers')
registerWindowHandlers()
const handler = handlers.get(IPC_CHANNELS.SYSTEM.OPEN_EXTERNAL)!
const appEvent = { senderFrame: { url: 'file:///C:/app/index.html' } }
const appEvent = { senderFrame: { url: `${appRendererFileRoot()}index.html` } }
const remoteEvent = { senderFrame: { url: 'https://evil.example/' } }
await expect(handler(appEvent, { url: 'file:///C:/Windows/System32/calc.exe' })).resolves.toMatchObject({ success: false })