46 lines
1.9 KiB
TypeScript
46 lines
1.9 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { isAllowedExternalUrl, isAppOrigin } from '../src/url-policy'
|
|
|
|
describe('isAllowedExternalUrl', () => {
|
|
it('allows https and mailto by default', () => {
|
|
expect(isAllowedExternalUrl('https://d3ro.chanpaca.net/app/billing')).toBe(true)
|
|
expect(isAllowedExternalUrl('mailto:help@example.com')).toBe(true)
|
|
})
|
|
|
|
it.each([
|
|
'file:///C:/Windows/System32/calc.exe',
|
|
'javascript:alert(1)',
|
|
'search-ms:query=x&crumb=location:\\\\evil\\share',
|
|
'ms-msdt:/id PCWDiagnostic',
|
|
'\\\\evil.example\\share\\payload.exe',
|
|
'//evil.example/x',
|
|
'd3ro-voice://auth-callback#access_token=x',
|
|
'http://example.com',
|
|
'https://user:pass@example.com',
|
|
'',
|
|
'not a url',
|
|
])('rejects %s', (url) => {
|
|
expect(isAllowedExternalUrl(url)).toBe(false)
|
|
})
|
|
|
|
it('allows extra exact origins (dev web app) without widening schemes', () => {
|
|
const options = { allowOrigins: ['http://localhost:3000'] }
|
|
expect(isAllowedExternalUrl('http://localhost:3000/app/billing?tier=pro', options)).toBe(true)
|
|
expect(isAllowedExternalUrl('http://localhost:3001/app', options)).toBe(false)
|
|
expect(isAllowedExternalUrl('http://evil.example', options)).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('isAppOrigin', () => {
|
|
it('matches the packaged file renderer and the dev server origin only', () => {
|
|
const origins = ['file://', 'http://localhost:5173']
|
|
expect(isAppOrigin('file:///C:/app/resources/app.asar/out/renderer/index.html#/meetings', origins)).toBe(true)
|
|
expect(isAppOrigin('http://localhost:5173/#/settings', origins)).toBe(true)
|
|
expect(isAppOrigin('http://localhost:5174/', origins)).toBe(false)
|
|
expect(isAppOrigin('https://evil.example/', origins)).toBe(false)
|
|
})
|
|
|
|
it('does not treat file: as app origin unless allowed', () => {
|
|
expect(isAppOrigin('file:///C:/x.html', ['http://localhost:5173'])).toBe(false)
|
|
})
|
|
})
|