How to test an HTML sanitizer so the test means something
A sanitizer with green tests may be doing nothing. Three steps to test it so the suite measures what the sanitizer prevents.
Also in: Español
If you accept HTML from an editor, your sanitizer has green tests. The question is green against what.
A test that confirms <strong> survives also passes with return html. That test doesn't measure sanitizing: it measures that legitimate markup is still there.
1. Run the suite against nothing
Before running it against the sanitizer, run it against a pass-through, a function that returns the input unchanged.
In a real case, 18 of 23 tests failed. Those 18 are the ones that measure something: what the sanitizer must prevent. With the sanitizer in place, 23 of 23.
If your suite passes entirely against the pass-through, it isn't testing anything.
2. Test the whole document, through the real route
Testing the bare function isn't enough. Also test against the real HTTP route, in the browser with a session cookie, with four inputs:
- a
<script> - an
onerror= - an
hrefwithjavascript: - an
onerrorinside thehtmlescape hatch
None survived, and the legitimate markup did.
3. Let the tests find the sanitizer's own bugs
Real bugs turn up, for example two:
- Lowercasing. Lowercasing every name broke SVG:
viewBoxis case-sensitive. - Space after
<. Allowing a space between<and the name turned "a < b and c > d" into an open<b>.
Both came out of the sanitizer's own tests.
In short
Re-emit every tag from scratch instead of cleaning the one that arrived, test the whole document, and run the test against nothing before running it against the code.
Have a case where you want to see this running? Tell us what your business does and we'll build it on your material.