From 2e3aec81e73d2120421797cf700ca45dc925dc54 Mon Sep 17 00:00:00 2001 From: Patrick Toomey Date: Wed, 5 Mar 2014 09:03:27 -0600 Subject: [PATCH 1/9] initial attempt at CSP policy to see what breaks --- static/index.html | 34 ++-------------------------------- static/index.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 32 deletions(-) create mode 100644 static/index.js diff --git a/static/index.html b/static/index.html index 990e08915..5559058dc 100644 --- a/static/index.html +++ b/static/index.html @@ -3,39 +3,9 @@ - + diff --git a/static/index.js b/static/index.js new file mode 100644 index 000000000..179026a66 --- /dev/null +++ b/static/index.js @@ -0,0 +1,31 @@ +window.onload = function() { + var path = require('path'); + var ipc = require('ipc'); + try { + // Skip "?loadSettings=". + var loadSettings = JSON.parse(decodeURIComponent(location.search.substr(14))); + + // Start the crash reporter before anything else. + require('crash-reporter').start({ + productName: 'Atom', + companyName: 'GitHub', + // By explicitly passing the app version here, we could save the call + // of "require('remote').require('app').getVersion()". + extra: {_version: loadSettings.appVersion} + }); + + require('vm-compatibility-layer'); + require('coffee-script').register(); + require(path.resolve(__dirname, '..', 'src', 'coffee-cache')).register(); + require(loadSettings.bootstrapScript); + ipc.sendChannel('window-command', 'window:loaded') + } + catch (error) { + var currentWindow = require('remote').getCurrentWindow(); + currentWindow.setSize(800, 600); + currentWindow.center(); + currentWindow.show(); + currentWindow.openDevTools(); + console.error(error.stack || error); + } +} From fc543fc5a68157a25c37d6070cb4feb20a679f9c Mon Sep 17 00:00:00 2001 From: Patrick Toomey Date: Wed, 5 Mar 2014 09:32:49 -0600 Subject: [PATCH 2/9] add unsafe-eval for now --- static/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/index.html b/static/index.html index 5559058dc..71fade746 100644 --- a/static/index.html +++ b/static/index.html @@ -3,7 +3,7 @@ - + From 5e8213d45ff0fa3390e4871095e381eb6afb4537 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 5 Mar 2014 09:57:08 -0700 Subject: [PATCH 3/9] Add atom.allowUnsafeEval loophole and disable unsafe-eval again With Node.js baked in, there's no water-tight way to prevent users from evaluating code at runtime, at least with CSP alone. This is because node exposes a 'vm' module that allows scripts to be compiled. There's also `module._compile`, etc. I think a reasonable compromise is to protect users from eval'ing code by accident. This commit adds an atom.allowUnsafeEval method which re-enables eval in the dynamic scope of the given function. I then use this to compile the keystroke grammar which saves us the complexity of pre-compiling it during specs. What do people think? --- src/atom.coffee | 9 +++++++++ src/key-binding.coffee | 2 +- static/index.html | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index e85bbb120..b831b69c9 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -1,3 +1,4 @@ +vm = require 'vm' crypto = require 'crypto' ipc = require 'ipc' keytar = require 'keytar' @@ -527,3 +528,11 @@ class Atom extends Model delete window[key] else window[key] = value + + allowUnsafeEval: (fn) -> + oldEval = global.eval + try + global.eval = (source) -> vm.runInThisContext(source) + fn() + finally + global.eval = oldEval diff --git a/src/key-binding.coffee b/src/key-binding.coffee index 46b359858..57fbf4fcb 100644 --- a/src/key-binding.coffee +++ b/src/key-binding.coffee @@ -31,7 +31,7 @@ class KeyBinding catch keystrokePattern = fs.readFileSync(require.resolve('./keystroke-pattern.pegjs'), 'utf8') PEG = require 'pegjs' - @parser = PEG.buildParser(keystrokePattern) + atom.allowUnsafeEval => @parser = PEG.buildParser(keystrokePattern) @parser.parse(keystroke) diff --git a/static/index.html b/static/index.html index 71fade746..5559058dc 100644 --- a/static/index.html +++ b/static/index.html @@ -3,7 +3,7 @@ - + From 2d4797c84e14ea7e7e04f4b16040181c5a08b799 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 6 Mar 2014 18:56:09 -0700 Subject: [PATCH 4/9] Define allowUnsafeEval in an npm module --- package.json | 1 + src/atom.coffee | 9 --------- src/key-binding.coffee | 3 ++- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 60f07652f..231a7b8c7 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "mkdirp": "0.3.5", "keytar": "0.15.1", "less-cache": "0.12.0", + "loophole": "^0.1.0", "mixto": "1.x", "nslog": "0.5.0", "oniguruma": "1.x", diff --git a/src/atom.coffee b/src/atom.coffee index 23342736e..5905902cd 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -1,4 +1,3 @@ -vm = require 'vm' crypto = require 'crypto' ipc = require 'ipc' keytar = require 'keytar' @@ -529,11 +528,3 @@ class Atom extends Model delete window[key] else window[key] = value - - allowUnsafeEval: (fn) -> - oldEval = global.eval - try - global.eval = (source) -> vm.runInThisContext(source) - fn() - finally - global.eval = oldEval diff --git a/src/key-binding.coffee b/src/key-binding.coffee index 3ae1fa4a9..6a72b5283 100644 --- a/src/key-binding.coffee +++ b/src/key-binding.coffee @@ -1,6 +1,7 @@ _ = require 'underscore-plus' fs = require 'fs-plus' {specificity} = require 'clear-cut' +{allowUnsafeEval} = require 'loophole' module.exports = class KeyBinding @@ -37,7 +38,7 @@ class KeyBinding catch keystrokePattern = fs.readFileSync(require.resolve('./keystroke-pattern.pegjs'), 'utf8') PEG = require 'pegjs' - atom.allowUnsafeEval => @parser = PEG.buildParser(keystrokePattern) + allowUnsafeEval => @parser = PEG.buildParser(keystrokePattern) @parser.parse(keystroke) From 5d498392365b5d6b4a480351ef88a3e2791e89c6 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 6 Mar 2014 19:13:27 -0700 Subject: [PATCH 5/9] Don't require loophole unless we need it. Won't happen in production. --- src/key-binding.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/key-binding.coffee b/src/key-binding.coffee index 6a72b5283..0dbc73f20 100644 --- a/src/key-binding.coffee +++ b/src/key-binding.coffee @@ -1,7 +1,6 @@ _ = require 'underscore-plus' fs = require 'fs-plus' {specificity} = require 'clear-cut' -{allowUnsafeEval} = require 'loophole' module.exports = class KeyBinding @@ -36,6 +35,7 @@ class KeyBinding try @parser = require './keystroke-pattern' catch + {allowUnsafeEval} = require 'loophole' keystrokePattern = fs.readFileSync(require.resolve('./keystroke-pattern.pegjs'), 'utf8') PEG = require 'pegjs' allowUnsafeEval => @parser = PEG.buildParser(keystrokePattern) From bfdcbbe9f1a5746d4433d701ce1a3851bc57e2af Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 6 Mar 2014 19:19:04 -0700 Subject: [PATCH 6/9] Upgrade to snippets@0.36.0 for CSP support in dev-mode --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 231a7b8c7..b4448ab32 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "package-generator": "0.30.0", "release-notes": "0.26.0", "settings-view": "0.89.0", - "snippets": "0.35.0", + "snippets": "0.36.0", "spell-check": "0.28.0", "status-bar": "0.35.0", "styleguide": "0.26.0", From dd27a35039a002ef44cfa713f8f65170fb38cc64 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 7 Mar 2014 17:01:51 -0700 Subject: [PATCH 7/9] Silence CSP warnings from q's feature detection --- package.json | 2 +- src/atom.coffee | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b483b1bf..1dbc4b79a 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "mkdirp": "0.3.5", "keytar": "0.15.1", "less-cache": "0.12.0", - "loophole": "^0.1.0", + "loophole": "^0.2.0", "mixto": "1.x", "nslog": "0.5.0", "oniguruma": "1.x", diff --git a/src/atom.coffee b/src/atom.coffee index 5905902cd..724352765 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -11,9 +11,15 @@ _ = require 'underscore-plus' {Model} = require 'theorist' fs = require 'fs-plus' +# this prevents CSP-related warnings for q's feature detection +{allowUnsafeNewFunction} = require 'loophole' +allowUnsafeNewFunction -> require 'q' + {$} = require './space-pen-extensions' WindowEventHandler = require './window-event-handler' + + # Public: Atom global for dealing with packages, themes, menus, and the window. # # An instance of this class is always available as the `atom` global. From aa6811a08852a16e12f3825429fee98c5557fbd3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 7 Mar 2014 17:13:11 -0700 Subject: [PATCH 8/9] Upgrade to loophole@0.3.0 for bugfix --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1dbc4b79a..cdfc02482 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "mkdirp": "0.3.5", "keytar": "0.15.1", "less-cache": "0.12.0", - "loophole": "^0.2.0", + "loophole": "^0.3.0", "mixto": "1.x", "nslog": "0.5.0", "oniguruma": "1.x", From 79089ced9790e2a94838ceb6fde0fa06fbedad48 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 7 Mar 2014 17:19:53 -0700 Subject: [PATCH 9/9] :lipstick: whitespace --- src/atom.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/atom.coffee b/src/atom.coffee index 724352765..b6a1da5e7 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -18,8 +18,6 @@ allowUnsafeNewFunction -> require 'q' {$} = require './space-pen-extensions' WindowEventHandler = require './window-event-handler' - - # Public: Atom global for dealing with packages, themes, menus, and the window. # # An instance of this class is always available as the `atom` global.