Bug 776606 - Possible chrome-level JS injection attack with user portraits in the Social API. r=gavin
☠☠ backed out by 83caf3e51946 ☠ ☠
authorJared Wein <jwein@mozilla.com>
Mon, 30 Jul 2012 19:28:23 -0700
changeset 100925 56e0971c81ead2dafafe93a39a4ee63ced8bb169
parent 100924 a57c83db51a72b1df7362283ff8d8fc0eb5f9eba
child 100926 df1d8e3c45cb1e76ea97438e48128683aec01075
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersgavin
bugs776606
milestone17.0a1
Bug 776606 - Possible chrome-level JS injection attack with user portraits in the Social API. r=gavin
browser/base/content/browser-social.js
toolkit/components/social/SocialService.jsm
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -155,20 +155,20 @@ let SocialShareButton = {
   init: function SSB_init() {
     this.updateButtonHiddenState();
     this.updateProfileInfo();
   },
 
   updateProfileInfo: function SSB_updateProfileInfo() {
     let profileRow = document.getElementById("editSharePopupHeader");
     let profile = Social.provider.profile;
-    if (profile && profile.portrait && profile.displayName) {
+    if (profile && profile.displayName) {
       profileRow.hidden = false;
       let portrait = document.getElementById("socialUserPortrait");
-      portrait.style.listStyleImage = profile.portrait;
+      portrait.setAttribute("src", profile.portrait || "chrome://browser/skin/social/social.png");
       let displayName = document.getElementById("socialUserDisplayName");
       displayName.setAttribute("label", profile.displayName);
     } else {
       profileRow.hidden = true;
     }
   },
 
   get shareButton() {
--- a/toolkit/components/social/SocialService.jsm
+++ b/toolkit/components/social/SocialService.jsm
@@ -196,16 +196,30 @@ SocialProvider.prototype = {
   //   name, iconURL, counter, contentPanel
   // See https://github.com/mozilla/socialapi-dev/blob/develop/docs/socialAPI.md
   ambientNotificationIcons: null,
 
   // Called by the workerAPI to update our profile information.
   updateUserProfile: function(profile) {
     this.profile = profile;
 
+    // Sanitize the portrait from any potential script-injection.
+    if (profile.portrait) {
+      try {
+        let portraitUri = Services.io.newURI(profile.portrait, null, null);
+
+        let scheme = portraitUri ? portraitUri.scheme : "";
+        if (scheme != "data" && scheme != "http" && scheme != "https") {
+          profile.portrait = "";
+        }
+      } catch (ex) {
+        profile.portrait = "";
+      }
+    }
+
     if (profile.iconURL)
       this.iconURL = profile.iconURL;
 
     if (!profile.displayName)
       profile.displayName = profile.userName;
 
     // if no userName, consider this a logged out state, emtpy the
     // users ambient notifications.  notify both profile and ambient