Yehuda Goldner
Yehuda Goldner

Reputation: 49

Why is my extension rejected by the Chrome Web Store as "obfuscating"?

I keep getting this message:

"We routinely review items in the Chrome Web Store for compliance with ourProgram policies to ensure a safe and trusted experience for our users. Your item "$myitem" $mycode is being taken down as it currently violates the section of the Developer Program Policy relating to Malicious Products as its obfuscating a part of code. Per our policies, where possible, make as much of your code visible in the package as you can. If some of your app's logic is hidden and it appears to be suspicious, we may remove it."

To have your item reinstated, please make any necessary changes to ensure:

All of the files and code are included in the item’s package.

inside the package is human readable (no obfuscated or minified code).

Avoid requesting or executing remotely hosted code (including by referencing remote javascript files or executing code obtained by XHR requests)."All code

I rewrote my code to comply all of it and I stil keep getting this.

This is my code:

function SuperM(){
  
  this.disabled = false
  this.$about = false   
  this.init = function(){
      
      
      
      //verefying script tool runs only once
      if(typeof contextPreContext != 'undefined')
        return  
      
      contextPreContext = true
      
      me.loadingAssets()   
      
      $( window ).scroll(function() {
            if(typeof me.$sm != "undefined")
                me.$sm.remove()
        });
      document.addEventListener('click', me.openToolMenu);
      $(document).keyup(function(e) {
           if (e.keyCode == 27) { // escape key maps to keycode `27`
              me.$sm.remove()    
          }
          
          if (e.keyCode == 121&& e.ctrlKey) { // escape key maps to keycode `27`
              me.openPopup("https://translate.google.com/?q=", 761, 550)   
          }
          
          
      });
      
      //
        me.selectFrominput()
      $('a').hover(function(e){
          console.log(e.ctrlKey)
          if(e.ctrlKey) {
              me.openToolMenu(e,0, $(this).text())
          }
      }, function(){
          //me.$sm.remove()
      })
      
  }
  
  this.loadingAssets = function(){
      //Loading the about window HTML
      //PLUGIN_ASSETS
      $.get(chrome.extension.getURL("about.html"), function(d){
          me.aboutTpl = d
      })
    
     //Loading the menu  HTML     
      $.get(chrome.extension.getURL("menu.html"), function(d){
          me.smTpl = d
      })
      //font awesome
      var fa = document.createElement('style');
            fa.type = 'text/css';
            fa.textContent = '@font-face { font-family: FontAwesome; src: url("'
                + chrome.extension.getURL('font-awesome/fonts/fontawesome-webfont.woff')
                + '"); }';
        document.head.appendChild(fa);
      $('<link rel="stylesheet" href="'+chrome.extension.getURL('font-awesome/css/font-awesome.css')+'">')  
        .appendTo('body');
        
      //END_PLUGIN_ASSETS
      
      
      
      
  }
  
  //Get the hightlight text
  
  this.getSelected = function(e){        
        var html=window.getSelection().toString()
        if(!html)
            html='';
        if(html.length>500)
            html=html.substr(0,500)
        return html.replace(/\s+/g,' ').replace(/^\s+|\s+$/g,'');
  }
 
 
    //Set the menu position
  this.pos = function(ev,el){
                var fontsize=parseInt($(ev.target).css("font-size").replace("px",""))
                var left=ev.pageX-$(document).scrollLeft();
                var dirx="W"
                dirx=(ev.pageX>innerWidth-el.width())?"E":"W"
                
                //Make some delta between the menu and the text
                if(dirx=="W")
                    left-=50
                else
                    left-=el.width()-50

                var top=ev.pageY-$(document).scrollTop();
                var diry=(top>$(window).height()-el.height()-62)?"S":"N";
                

                if(diry=="N")
                    top+=15+fontsize
                else
                    top-=35+el.height()+fontsize


                //Set the menu position
                el.addClass("contextPre"+diry+dirx)             
                el.css('top',top);
                el.css('left',left);
            },
 
    //Use the url to open popup
  this.openPopup = function(url,width, height){          
        //close previus popup if exist
        if(me.popup!=undefined)
          me.popup.close()
        
        //Encoding the text
        var q=encodeURIComponent(me.text.toLowerCase().replace(/^[\s\!@#\$%\^&\*\(\)\-_=\+\[\]{}\\\/]+|[\s\!@#\$%\^&\*\(\)\-_=\+\[\]{}\\\/]+$/g,''))
          .replace(/'/g,"%27")
          url = url.replace("[q]", q)
        
        //getThe text language and use it in the url if needed
        var lang =   "en"  
        guessLanguage.info(me.text, function(info) {
            if(info[0] !== "unknown") {
                lang = info[0]
                
            }
        });         
        url = url.replace("[lang]", lang)
        
        //open the popup
        me.popup=window.open(url,"popup","height="+height+", left="+(innerWidth/2-200)+",scrollbars=no, width="+width+", top="+(innerHeight/2-290)+", menuba=0,location=0,status=0,titlebar=0,toolbar=0")
        return;         
  }

    
  this.openToolMenu = function(e, isDB, selection){
      if(me.$sm!=undefined)
          me.$sm.remove()
      if(selection)
        me.text = selection
      else{
        var q = me.getSelected(e)  
        if(q)
            me.text = q 
        else 
            return
      }
      
      
      if(me.$sm!=undefined)
          me.$sm.remove()
      
      if(selection == undefined) {
          if(!e.ctrlKey||e.which!=1||e.target.tagName=="EMBED"||!me.text||me.disabled){        
            return;
          }
      }
      me.$sm = $(me.smTpl)              
            
      setTimeout(me.menuHandler)
            
      me.pos(e, me.$sm)
      

  }
  
  // append the menu to the body and handle menu events
  this.menuHandler = function(){
                
                me.$sm.appendTo("body")
                .find('.contextPreSelItm')
                  .click(me.menuEvents)
                  
                  me.$sm.find('.contextPrex')
                      .click(me.closeMenu)
                      
                      me.$sm.find('.contextPrehelp')
                      .click(me.openAbout)
                $('.hideSmForSession').click(function(){
                    me.disabled = true
                })  
                
                
            }
            
    //Take the menu.html's item parameters and openPopup        
    this.menuEvents = function(e){
                    e.preventDefault();
                    e.stopPropagation();
                    me.openPopup($(this).attr("url"), $(this).attr("width"), $(this).attr("height"))
                  }     
                  
                  
    this.closeMenu = function(e){
                        
                        e.preventDefault();
                        e.stopPropagation();
                        $('.contextPresmhidemenu').show()
                      }           
  
  this.openAbout = function(e){                 
        
        e.preventDefault();
        e.stopPropagation();
        
        
        if(!me.$about)
        me.$about = $(me.aboutTpl)
            .appendTo("body")
            
        me.$about.find(".contextPreclose")
            .click(function(){
                me.$about.remove()
                me.$about = false
            })
            .after("<img src='"+chrome.extension.getURL("icon.png")+"' class='contextPre-reset'>")
        
            
      }
                      
  this.selectFrominput = function() {
    $('input,textarea').click(function(e){
            if(e.which!=1 || !e.ctrlKey)
                return
            
            // obtain the index of the first selected character
            var start = $(this)[0].selectionStart;
            // obtain the index of the last selected character
            var finish = $(this)[0].selectionEnd;
            // obtain the selected text
            var sel = $(this)[0].value.substring(start, finish);
            console.log(sel)
            me.openToolMenu(e,0, sel)
        
    })
    
    // do something with the selected content
}
  
  var me = this
  this.init()
}

//LOADING_LIBS  
new SuperM();

//END_LOADING_LIBS

This is my manifest.json:

{
  "manifest_version": 2,

  "name": "Context",
  "description": "Context is a menu that opens when one press CTRL & highlight text. It allows to explore the hightlited text without leaving the site",
  "version": "1.10",

  "icons": { "16": "icon16.png",
           "32": "icon32.png",
          "128": "icon.png" },
 "web_accessible_resources": [      
        "font-awesome/css/*",
        "font-awesome/fonts/*",
        "about.html",
        "menu.html",
        "icon.png"
    ], 
    
  "content_scripts": [
    {
      "matches": ["http://*/*","https://*/*"],
       "css": ["style.css"],
      "js": [ "jquery.js", "guessLanguage.js","context.js"],
      "run_at": "document_end"
    }
  ],
  "permissions": [
    "activeTab",
    "tabs",
    "http://*/*",
    "http://*/*"
  ]
}

This is a screenshot of my app:

enter image description here

Upvotes: 1

Views: 615

Answers (1)

Noam Hacker
Noam Hacker

Reputation: 4835

The Chrome Web Store likely has a bot which looks through the code and uses a certain formula to guess that an extension has a good chance of being malicious. Something in your code is being picked up by this bot and being marked as "malicious".

From Chrome's Developer Program Policies page:

Malicious Products: Don't transmit viruses, worms, defects, Trojan horses, malware, or any other items of a destructive nature. We don't allow content that harms or interferes with the operation of the networks, servers, or other infrastructure of Google or any third-parties. Spyware, malicious scripts, and password phishing scams are also prohibited in the Chrome Web Store. Where possible, make as much of your code visible in the package as you can. If some of your app's logic is hidden and it appears to be suspicious, we may remove it.

Basically, Google thinks your code is hiding something, due to the way it is written. Some tips I can come up with:

  1. your script is poorly indented, and this may be making google think your code is obfuscated. Try putting your code through a javascript beautifier so it is more readable and looks more human-written.
  2. use descriptive variable names
  3. I have a guess that the (non-jquery) dollar signs in your script may be affecting google's parser. see the discussion here. could google think your dollar signs are results of "mechanically generated code"? try experimenting with changing your variable names to remove the dollar signs.
  4. you can't run external code from an extension so be careful of xhr requests (didn't see any in your code though)

Upvotes: 2

Related Questions