diff --git a/CHANGELOG.md b/CHANGELOG.md index 6371ecc0..b2d00347 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Release date: TBD #### All platforms - Changed display of unread messages on the team tabbar, they are now shown as bold text - Reload only the selected tab and keep its URL on "Reload" and "Clear Cache and Reload". +- Disabled `eval()` function for security improvements. #### Windows - Update Mattermost icon for desktop notifications in Windows 10. diff --git a/src/browser/index.jsx b/src/browser/index.jsx index 24a1e902..364713ee 100644 --- a/src/browser/index.jsx +++ b/src/browser/index.jsx @@ -1,5 +1,9 @@ 'use strict'; +window.eval = global.eval = function() { + throw new Error("Sorry, Mattermost does not support window.eval() for security reasons."); +} + const React = require('react'); const ReactDOM = require('react-dom'); const ReactBootstrap = require('react-bootstrap'); @@ -428,7 +432,7 @@ var MattermostView = React.createClass({ // Need to keep webview mounted when failed to load. return (
{ errorView } - +
); } }); diff --git a/src/browser/settings.jsx b/src/browser/settings.jsx index d3fd9644..62651296 100644 --- a/src/browser/settings.jsx +++ b/src/browser/settings.jsx @@ -1,5 +1,9 @@ 'use strict'; +window.eval = global.eval = function() { + throw new Error("Sorry, Mattermost does not support window.eval() for security reasons."); +} + const {remote, ipcRenderer} = require('electron'); const settings = require('../common/settings'); diff --git a/src/browser/webview/mattermost.js b/src/browser/webview/mattermost.js index b9679f60..92ed1043 100644 --- a/src/browser/webview/mattermost.js +++ b/src/browser/webview/mattermost.js @@ -4,6 +4,10 @@ const electron = require('electron'); const ipc = electron.ipcRenderer; const notification = require('../js/notification'); +window.eval = global.eval = function() { + throw new Error("Sorry, Mattermost does not support window.eval() for security reasons."); +} + var hasClass = function(element, className) { var rclass = /[\t\r\n\f]/g; if ((' ' + element.className + ' ').replace(rclass, ' ').indexOf(className) > -1) { diff --git a/test/specs/security_test.js b/test/specs/security_test.js index 1766e083..9c0f22c6 100644 --- a/test/specs/security_test.js +++ b/test/specs/security_test.js @@ -76,5 +76,30 @@ describe('application', function() { }); }, 5000, 'expected a new window') .windowByIndex(3).isNodeEnabled().should.eventually.be.false; - }) + }); + + it('should NOT be able to call eval() in any window', function() { + env.addClientCommands(this.app.client); + const tryEval = (index) => { + return this.app.client + .windowByIndex(index) + .execute(function() { + return eval('1 + 1'); + }).should.eventually.be.rejected; + }; + const tryEvalInSettingsPage = () => { + return this.app.client + .windowByIndex(0) + .loadSettingsPage() + .execute(function() { + return eval('1 + 1'); + }).should.eventually.be.rejected; + }; + return Promise.all([ + tryEval(0), + tryEval(1), + tryEval(2), + tryEvalInSettingsPage() + ]); + }); });