Skip to content

Commit

Permalink
Add sanitize function
Browse files Browse the repository at this point in the history
  • Loading branch information
mirka committed Feb 16, 2022
1 parent 594c596 commit 83427bf
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import sanitizeHTML from '../sanitize-html';

describe( 'sanitizeHTML', () => {
it( 'should remove script tags', () => {
expect( sanitizeHTML( 'hello<script>alert();</script>world' ) ).toEqual(
expect.not.stringContaining( 'alert' )
);
} );

it( 'should remove on* attributes', () => {
expect( sanitizeHTML( '<button onclick="alert()">click</button>' ) ).toEqual(
expect.not.stringContaining( 'alert' )
);
} );

it( 'should keep incomplete HTML intact if there is nothing to be sanitized', () => {
const html = '<button>still typing</bu';
expect( sanitizeHTML( html ) ).toBe( html );
} );

it( 'should sanitize incomplete HTML if it is already dangerous', () => {
expect( sanitizeHTML( '<button onclick="alert()">still typing</bu' ) ).toEqual(
expect.not.stringContaining( 'alert' )
);
} );
} );
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { remove } from '@wordpress/dom';

/**
* Strips scripts and on* attributes from HTML.
*
* Slightly modified version of wp.dom.safeHTML() that only alters the
* HTML if it actually finds nodes/attributes to remove. This is so we can leave
* invalid HTML intact, for example if a user is still in the middle of typing the HTML string.
*
* @param {string} html HTML to sanitize.
*
* @return {string} The sanitized HTML.
*/
export default function sanitizeHTML( html ) {
const { body } = document.implementation.createHTMLDocument( '' );
body.innerHTML = html;
const elements = body.getElementsByTagName( '*' );
let elementIndex = elements.length;
let found = 0;

while ( elementIndex-- ) {
const element = elements[ elementIndex ];

if ( element.tagName === 'SCRIPT' ) {
found++;
remove( element );
} else {
let attributeIndex = element.attributes.length;

while ( attributeIndex-- ) {
const { name: key } = element.attributes[ attributeIndex ];

if ( key.startsWith( 'on' ) ) {
found++;
element.removeAttribute( key );
}
}
}
}

return found ? body.innerHTML : html;
}

0 comments on commit 83427bf

Please sign in to comment.