Fix XSS in app launcher and remove use of unvalidated URL
The third parameter of "launchApp" is only used for the webstore app,
and used to append utm_source=chrome-ntp-icon to the app URL.
But the launchApp handler did not validate that the URL is safe.
To fix that issue, I specialize the parameter for launchApp: It now takes the
source string ("chrome-ntp-icon") instead of a URL without validation.
BUG=668665
TEST=Manually using test case from bug report. Also opened the app launcher and
verified that clicking on the Webstore icon still leads to the same place.
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:closure_compilation
Review-Url: https://codereview.chromium.org/2527413002
Cr-Commit-Position: refs/heads/master@{#434939}
(cherry picked from commit 15120efa4b9394086d687086e443f47290b5170a)
Review URL: https://codereview.chromium.org/2542593002 .
Cr-Commit-Position: refs/branch-heads/2924@{#186}
Cr-Branched-From: 3a87aecc31cd1ffe751dd72c04e5a96a1fc8108a-refs/heads/master@{#433059}
diff --git a/chrome/browser/resources/ntp4/apps_page.js b/chrome/browser/resources/ntp4/apps_page.js
index e1f4a00..9e7b71e6 100644
--- a/chrome/browser/resources/ntp4/apps_page.js
+++ b/chrome/browser/resources/ntp4/apps_page.js
@@ -396,13 +396,8 @@
onClick_: function(e) {
if (/** @type {MouseEvent} */(e).button > 1) return;
- var url = !this.appData_.is_webstore ? '' :
- appendParam(this.appData_.url,
- 'utm_source',
- 'chrome-ntp-icon');
-
chrome.send('launchApp',
- [this.appId, APP_LAUNCH.NTP_APPS_MAXIMIZED, url,
+ [this.appId, APP_LAUNCH.NTP_APPS_MAXIMIZED, 'chrome-ntp-icon',
e.button, e.altKey, e.ctrlKey, e.metaKey, e.shiftKey]);
// Don't allow the click to trigger a link or anything
@@ -709,9 +704,9 @@
if (html) {
// It's important that we don't attach this node to the document
// because it might contain scripts.
- var node = this.ownerDocument.createElement('div');
- node.innerHTML = html;
- title = node.textContent;
+ var doc = document.implementation.createHTMLDocument();
+ doc.body.innerHTML = html;
+ title = doc.body.textContent;
}
// Make sure title is >=1 and <=45 characters for Chrome app limits.
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index a8c2df6..0e2b5be 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -67,6 +67,7 @@
#include "extensions/common/extension.h"
#include "extensions/common/extension_icon_set.h"
#include "extensions/common/extension_set.h"
+#include "net/base/url_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/webui/web_ui_util.h"
#include "url/gurl.h"
@@ -482,9 +483,7 @@
CHECK(args->GetString(0, &extension_id));
double source = -1.0;
CHECK(args->GetDouble(1, &source));
- std::string url;
- if (args->GetSize() > 2)
- CHECK(args->GetString(2, &url));
+ GURL override_url;
extension_misc::AppLaunchBucket launch_bucket =
static_cast<extension_misc::AppLaunchBucket>(
@@ -511,6 +510,16 @@
extensions::RecordAppLaunchType(launch_bucket, extension->GetType());
} else {
extensions::RecordWebStoreLaunch();
+
+ if (args->GetSize() > 2) {
+ std::string source_value;
+ CHECK(args->GetString(2, &source_value));
+ if (!source_value.empty()) {
+ override_url = net::AppendQueryParameter(
+ extensions::AppLaunchInfo::GetFullLaunchURL(extension),
+ extension_urls::kWebstoreSourceField, source_value);
+ }
+ }
}
if (disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB ||
@@ -522,7 +531,7 @@
? extensions::LAUNCH_CONTAINER_WINDOW
: extensions::LAUNCH_CONTAINER_TAB,
disposition, extensions::SOURCE_NEW_TAB_PAGE);
- params.override_url = GURL(url);
+ params.override_url = override_url;
OpenApplication(params);
} else {
// To give a more "launchy" experience when using the NTP launcher, we close
@@ -538,7 +547,7 @@
old_contents ? WindowOpenDisposition::CURRENT_TAB
: WindowOpenDisposition::NEW_FOREGROUND_TAB,
extensions::SOURCE_NEW_TAB_PAGE);
- params.override_url = GURL(url);
+ params.override_url = override_url;
WebContents* new_contents = OpenApplication(params);
// This will also destroy the handler, so do not perform any actions after.