47 lines
1.9 KiB
TypeScript
47 lines
1.9 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
trustedWorksProjectPlayUrl,
|
|
trustedWorksReleasePreviewUrl,
|
|
} from '@electron/api/works-play-url';
|
|
|
|
const worksBase = new URL('https://square.nianxx.cn/');
|
|
|
|
describe('Works Square playable URL security', () => {
|
|
it('normalizes only the exact same-origin HTTPS app path', () => {
|
|
expect(trustedWorksProjectPlayUrl('/apps/space-cleaner/', worksBase, 'space-cleaner'))
|
|
.toBe('https://square.nianxx.cn/apps/space-cleaner/');
|
|
expect(trustedWorksProjectPlayUrl(
|
|
'/apps/space%20cleaner/',
|
|
worksBase,
|
|
'space cleaner',
|
|
)).toBe('https://square.nianxx.cn/apps/space%20cleaner/');
|
|
});
|
|
|
|
it.each([
|
|
['cross origin', 'https://evil.example/apps/space-cleaner/', worksBase],
|
|
['HTTP', 'http://square.nianxx.cn/apps/space-cleaner/', worksBase],
|
|
['userinfo', 'https://user:secret@square.nianxx.cn/apps/space-cleaner/', worksBase],
|
|
['loopback base', '/apps/space-cleaner/', new URL('https://127.0.0.1:8443/')],
|
|
['wrong app path', '/apps/another-app/', worksBase],
|
|
['nested path', '/apps/space-cleaner/index.html', worksBase],
|
|
['query string', '/apps/space-cleaner/?token=secret', worksBase],
|
|
['fragment', '/apps/space-cleaner/#start', worksBase],
|
|
['overlong URL', `/apps/space-cleaner/${'x'.repeat(1_100)}`, worksBase],
|
|
])('rejects %s', (_case, value, base) => {
|
|
expect(trustedWorksProjectPlayUrl(value, base, 'space-cleaner')).toBeNull();
|
|
});
|
|
|
|
it('keeps signed release previews on their exact release prefix', () => {
|
|
expect(trustedWorksReleasePreviewUrl(
|
|
'/previews/release-7/signed-ticket/?signature=ok',
|
|
worksBase,
|
|
'release-7',
|
|
)).toBe('https://square.nianxx.cn/previews/release-7/signed-ticket/?signature=ok');
|
|
expect(trustedWorksReleasePreviewUrl(
|
|
'/previews/release-8/signed-ticket/',
|
|
worksBase,
|
|
'release-7',
|
|
)).toBeNull();
|
|
});
|
|
});
|