Files
site-builder/craft/src/components/basic/HtmlBlock.toHtml.test.ts
T

36 lines
1.5 KiB
TypeScript
Raw Normal View History

import { describe, test, expect } from 'vitest';
import { HtmlBlock } from './HtmlBlock';
const toHtml = (HtmlBlock as any).toHtml;
describe('HtmlBlock.toHtml sanitizes raw code (A4.1)', () => {
test('strips <script> and on-handlers from exported output', () => {
const { html } = toHtml({ code: '<script>alert(1)</script><p onclick="x">hi</p>' }, '');
expect(html).not.toContain('<script');
expect(html).not.toContain('onclick');
expect(html).toContain('<p>hi</p>');
});
test('does not wrap output in an unsanitized element carrying the style prop raw', () => {
// toHtml only ever returns the sanitized `code` blob -- there is no
// wrapper <div style="..."> in the exported HTML, so a malicious
// `style` prop (e.g. an attacker-controlled object with a breakout
// toString()) has nothing to splice into.
const malicious = { toString: () => 'color:red" onmouseover="alert(1)' } as any;
const { html } = toHtml({ code: '<p>hi</p>', style: malicious }, '');
expect(html).not.toMatch(/onmouseover/);
expect(html).not.toMatch(/<div/);
expect(html).toBe('<p>hi</p>');
});
});
test('toHtml never emits the style prop (the other half of the render/export contract)', () => {
const out = (HtmlBlock as any).toHtml(
{ code: '<p>hi</p>', style: { backgroundColor: '#ff0000', padding: '40px' } },
'',
);
expect(out.html).toBe('<p>hi</p>');
expect(out.html).not.toContain('background');
expect(out.html).not.toContain('40px');
});