35 lines
1.3 KiB
TypeScript
35 lines
1.3 KiB
TypeScript
import { describe, test, expect } from 'vitest';
|
|||
|
|
import { ImageBlock } from './ImageBlock';
|
||
|
|
|
||
|
|
const toHtml = (ImageBlock as any).toHtml;
|
||
|
|
|
||
|
|
describe('ImageBlock.toHtml src/alt XSS hardening', () => {
|
||
|
|
test('a javascript: src never reaches the output', () => {
|
||
|
|
const { html } = toHtml({ src: 'javascript:alert(1)' }, '');
|
||
|
|
expect(html).not.toContain('javascript:');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('a malicious src cannot break out of the src attribute', () => {
|
||
|
|
const malicious = 'https://example.com/x.jpg" onerror="alert(1)';
|
||
|
|
const { html } = toHtml({ src: malicious }, '');
|
||
|
|
expect(html).not.toContain('onerror="alert(1)"');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('a malicious alt cannot break out of the alt attribute', () => {
|
||
|
|
const malicious = 'x" onerror="alert(1)';
|
||
|
|
const { html } = toHtml({ src: 'https://example.com/x.jpg', alt: malicious }, '');
|
||
|
|
expect(html).not.toContain('onerror="alert(1)"');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('a placeholder/empty src emits no output', () => {
|
||
|
|
const { html } = toHtml({ src: '' }, '');
|
||
|
|
expect(html).toBe('');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('a normal image still renders correctly', () => {
|
||
|
|
const { html } = toHtml({ src: 'https://example.com/photo.jpg', alt: 'A photo' }, '');
|
||
|
|
expect(html).toContain('src="https://example.com/photo.jpg"');
|
||
|
|
expect(html).toContain('alt="A photo"');
|
||
|
|
});
|
||
|
|
});
|