Commit a911cf81 authored by Oliver Hader's avatar Oliver Hader Committed by Benni Mack
Browse files

[TASK] Harden client-side SecurityUtility.encodeHtml

Ensures client-side function `SecurityUtility.encodeHtml` behaves like
`htmlspecialchars(..., ENT_QUOTES)`. The function is used for complete
nodes only, but now could be used for parts as well.

Resolves: #93068
Releases: master, 10.4, 9.5
Change-Id: I74b09676d0fdb8ddf09e7fc639480742fe645e9b
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67107

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent f5003fd1
......@@ -66,7 +66,9 @@ class SecurityUtility {
// apply arbitrary data a text node
// thus browser is capable of properly encoding
anvil.innerText = value;
return anvil.innerHTML;
return anvil.innerHTML
.replace(/"/g, '&quot;')
.replace(/'/g, '&apos;');
}
/**
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
define(["require","exports"],(function(e,t){"use strict";return function(){function e(e){void 0===e&&(e=document),this.documentRef=e}return e.prototype.getRandomHexValue=function(e){if(e<=0||e!==Math.ceil(e))throw new SyntaxError("Length must be a positive integer");var t=new Uint8Array(Math.ceil(e/2)),n=[];crypto.getRandomValues(t);for(var r=0;r<t.byteLength;r++)n[r]=t[r];return n.map((function(e){var t=e.toString(16);return 2===t.length?t:"0"+t})).join("").substr(0,e)},e.prototype.encodeHtml=function(e,t){void 0===t&&(t=!0);var n=this.createAnvil();return t||(e=e.replace(/&[#A-Za-z0-9]+;/g,(function(e){return n.innerHTML=e,n.innerText}))),n.innerText=e,n.innerHTML},e.prototype.debug=function(e){e!==this.encodeHtml(e)&&console.warn("XSS?!",e)},e.prototype.createAnvil=function(){return this.documentRef.createElement("span")},e}()}));
\ No newline at end of file
define(["require","exports"],(function(e,t){"use strict";return function(){function e(e){void 0===e&&(e=document),this.documentRef=e}return e.prototype.getRandomHexValue=function(e){if(e<=0||e!==Math.ceil(e))throw new SyntaxError("Length must be a positive integer");var t=new Uint8Array(Math.ceil(e/2)),n=[];crypto.getRandomValues(t);for(var r=0;r<t.byteLength;r++)n[r]=t[r];return n.map((function(e){var t=e.toString(16);return 2===t.length?t:"0"+t})).join("").substr(0,e)},e.prototype.encodeHtml=function(e,t){void 0===t&&(t=!0);var n=this.createAnvil();return t||(e=e.replace(/&[#A-Za-z0-9]+;/g,(function(e){return n.innerHTML=e,n.innerText}))),n.innerText=e,n.innerHTML.replace(/"/g,"&quot;").replace(/'/g,"&apos;")},e.prototype.debug=function(e){e!==this.encodeHtml(e)&&console.warn("XSS?!",e)},e.prototype.createAnvil=function(){return this.documentRef.createElement("span")},e}()}));
\ No newline at end of file
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
var __values=this&&this.__values||function(e){var r="function"==typeof Symbol&&e[Symbol.iterator],t=0;return r?r.call(e):{next:function(){return e&&t>=e.length&&(e=void 0),{value:e&&e[t++],done:!e}}}};define(["require","exports","TYPO3/CMS/Core/SecurityUtility"],(function(e,r,t){"use strict";Object.defineProperty(r,"__esModule",{value:!0}),describe("TYPO3/CMS/Core/SecurityUtility",(function(){it("generates random hex value",(function(){try{for(var e=__values([1,20,39]),r=e.next();!r.done;r=e.next()){var n=r.value,o=(new t).getRandomHexValue(n);expect(o.length).toBe(n)}}catch(e){a={error:e}}finally{try{r&&!r.done&&(i=e.return)&&i.call(e)}finally{if(a)throw a.error}}var a,i})),it("throws SyntaxError on invalid length",(function(){var e,r,n=function(e){expect((function(){return(new t).getRandomHexValue(e)})).toThrowError(SyntaxError)};try{for(var o=__values([0,-90,10.3]),a=o.next();!a.done;a=o.next()){n(a.value)}}catch(r){e={error:r}}finally{try{a&&!a.done&&(r=o.return)&&r.call(o)}finally{if(e)throw e.error}}}))}))}));
\ No newline at end of file
var __values=this&&this.__values||function(e){var t="function"==typeof Symbol&&e[Symbol.iterator],r=0;return t?t.call(e):{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}}};define(["require","exports","TYPO3/CMS/Core/SecurityUtility"],(function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),describe("TYPO3/CMS/Core/SecurityUtility",(function(){it("generates random hex value",(function(){try{for(var e=__values([1,20,39]),t=e.next();!t.done;t=e.next()){var n=t.value,o=(new r).getRandomHexValue(n);expect(o.length).toBe(n)}}catch(e){a={error:e}}finally{try{t&&!t.done&&(i=e.return)&&i.call(e)}finally{if(a)throw a.error}}var a,i})),it("throws SyntaxError on invalid length",(function(){var e,t,n=function(e){expect((function(){return(new r).getRandomHexValue(e)})).toThrowError(SyntaxError)};try{for(var o=__values([0,-90,10.3]),a=o.next();!a.done;a=o.next()){n(a.value)}}catch(t){e={error:t}}finally{try{a&&!a.done&&(t=o.return)&&t.call(o)}finally{if(e)throw e.error}}})),it("encodes HTML",(function(){expect((new r).encodeHtml("<>\"'&")).toBe("&lt;&gt;&quot;&apos;&amp;")}))}))}));
\ No newline at end of file
......@@ -40,4 +40,8 @@ describe('TYPO3/CMS/Core/SecurityUtility', (): void => {
expect(() => (new SecurityUtility()).getRandomHexValue(invalidLength)).toThrowError(SyntaxError);
}
});
it('encodes HTML', (): void => {
expect((new SecurityUtility).encodeHtml('<>"\'&')).toBe('&lt;&gt;&quot;&apos;&amp;');
});
});
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment