Merge pull request #196 from atom/iframe-security

Fix iframe security
This commit is contained in:
Cheng Zhao 2014-03-04 14:12:26 +00:00
commit a74d3d210d
6 changed files with 51 additions and 14 deletions

View file

@ -54,7 +54,7 @@ void AtomBrowserClient::OverrideWebkitPrefs(
const GURL& url, const GURL& url,
WebPreferences* prefs) { WebPreferences* prefs) {
prefs->javascript_enabled = true; prefs->javascript_enabled = true;
prefs->web_security_enabled = false; prefs->web_security_enabled = true;
prefs->javascript_can_open_windows_automatically = true; prefs->javascript_can_open_windows_automatically = true;
prefs->plugins_enabled = false; prefs->plugins_enabled = false;
prefs->dom_paste_enabled = true; prefs->dom_paste_enabled = true;

View file

@ -56,7 +56,7 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
: content::WebContentsObserver(web_contents), : content::WebContentsObserver(web_contents),
has_frame_(true), has_frame_(true),
is_closed_(false), is_closed_(false),
node_integration_("all"), node_integration_("except-iframe"),
has_dialog_attached_(false), has_dialog_attached_(false),
weak_factory_(this), weak_factory_(this),
inspectable_web_contents_( inspectable_web_contents_(

View file

@ -48,9 +48,9 @@ Creates a new `BrowserWindow` with native properties set by the `options`.
Usually you only need to set the `width` and `height`, other properties will Usually you only need to set the `width` and `height`, other properties will
have decent default values. have decent default values.
By default the `node-integration` option is `all`, which means node integration By default the `node-integration` option is `except-iframe`, which means node
is available to the main page and all its iframes. You can also set it to integration is disabled in all iframes, . You can also set it to `all`, with
`except-iframe`, which would disable node integration in all iframes, or which node integration is available to the main page and all its iframes, or
`manual-enable-iframe`, which is like `except-iframe`, but would enable iframes `manual-enable-iframe`, which is like `except-iframe`, but would enable iframes
whose name is suffixed by `-enable-node-integration`. And setting to `disable` whose name is suffixed by `-enable-node-integration`. And setting to `disable`
would disable the node integration in both the main page and its iframes. would disable the node integration in both the main page and its iframes.
@ -66,6 +66,14 @@ An example of enable node integration in iframe with `node-integration` set to
<iframe src="http://jandan.net"></iframe> <iframe src="http://jandan.net"></iframe>
``` ```
And you should also notice that the iframes can have access to parent window's
javascript objects via `window.parent`, so in order to grant complete security
from iframes, you should add `sandbox` attribute to the iframes:
```html
<iframe sandbox="allow-scripts" src="http://bbs.seu.edu.cn"></iframe>
```
### Event: 'page-title-updated' ### Event: 'page-title-updated'
* `event` Event * `event` Event

View file

@ -21,10 +21,11 @@ namespace atom {
namespace { namespace {
// Security tokens. // Security tokens.
const char* kExceptIframe = "except-iframe"; const char* kSecurityAll = "all";
const char* kManualEnableIframe = "manual-enable-iframe"; const char* kSecurityExceptIframe = "except-iframe";
const char* kDisable = "disable"; const char* kSecurityManualEnableIframe = "manual-enable-iframe";
const char* kEnableNodeIntegration = "enable-node-integration"; const char* kSecurityDisable = "disable";
const char* kSecurityEnableNodeIntegration = "enable-node-integration";
// Scheme used by devtools // Scheme used by devtools
const char* kChromeDevToolsScheme = "chrome-devtools"; const char* kChromeDevToolsScheme = "chrome-devtools";
@ -32,17 +33,19 @@ const char* kChromeDevToolsScheme = "chrome-devtools";
} // namespace } // namespace
AtomRendererClient::AtomRendererClient() AtomRendererClient::AtomRendererClient()
: node_integration_(ALL), : node_integration_(EXCEPT_IFRAME),
main_frame_(NULL) { main_frame_(NULL) {
// Translate the token. // Translate the token.
std::string token = CommandLine::ForCurrentProcess()-> std::string token = CommandLine::ForCurrentProcess()->
GetSwitchValueASCII(switches::kNodeIntegration); GetSwitchValueASCII(switches::kNodeIntegration);
if (token == kExceptIframe) if (token == kSecurityExceptIframe)
node_integration_ = EXCEPT_IFRAME; node_integration_ = EXCEPT_IFRAME;
else if (token == kManualEnableIframe) else if (token == kSecurityManualEnableIframe)
node_integration_ = MANUAL_ENABLE_IFRAME; node_integration_ = MANUAL_ENABLE_IFRAME;
else if (token == kDisable) else if (token == kSecurityDisable)
node_integration_ = DISABLE; node_integration_ = DISABLE;
else if (token == kSecurityAll)
node_integration_ = ALL;
if (IsNodeBindingEnabled()) { if (IsNodeBindingEnabled()) {
node_bindings_.reset(NodeBindings::Create(false)); node_bindings_.reset(NodeBindings::Create(false));
@ -164,7 +167,7 @@ bool AtomRendererClient::IsNodeBindingEnabled(WebKit::WebFrame* frame) {
return true; return true;
else if (node_integration_ == MANUAL_ENABLE_IFRAME && else if (node_integration_ == MANUAL_ENABLE_IFRAME &&
frame != NULL && frame != NULL &&
frame->uniqueName().utf8().find(kEnableNodeIntegration) frame->uniqueName().utf8().find(kSecurityEnableNodeIntegration)
== std::string::npos) == std::string::npos)
return false; return false;
else if (node_integration_ == EXCEPT_IFRAME && frame != NULL) else if (node_integration_ == EXCEPT_IFRAME && frame != NULL)

View file

@ -1,6 +1,9 @@
assert = require 'assert' assert = require 'assert'
path = require 'path'
describe 'chromium feature', -> describe 'chromium feature', ->
fixtures = path.resolve __dirname, 'fixtures'
describe 'heap snapshot', -> describe 'heap snapshot', ->
it 'does not crash', -> it 'does not crash', ->
process.atomBinding('v8_util').takeHeapSnapshot() process.atomBinding('v8_util').takeHeapSnapshot()
@ -21,3 +24,18 @@ describe 'chromium feature', ->
b = window.open 'about:blank', 'test', 'show=no' b = window.open 'about:blank', 'test', 'show=no'
assert.equal b.constructor.name, 'BrowserWindow' assert.equal b.constructor.name, 'BrowserWindow'
b.destroy() b.destroy()
describe 'iframe with sandbox attribute', ->
it 'can not modify parent', (done) ->
page = path.join fixtures, 'pages', 'change-parent.html'
global.changedByIframe = false
iframe = $('<iframe sandbox="allow-scripts">')
iframe.hide()
iframe.attr 'src', "file://#{page}"
iframe.appendTo 'body'
isChanged = ->
iframe.remove()
assert.equal global.changedByIframe, false
done()
setTimeout isChanged, 30

View file

@ -0,0 +1,8 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
console.log('ready2')
window.parent.changedByIframe = true;
</script>
</body>
</html>