4

I try to add bookmarklet button to my website with generating link in a controller.

Template part:

    <a id="bookmarklet"
       class="bookmarklet"
       onclick="alert('Drag and drop me to the bookmarks bar');return false;"
       href="{{getCode()}}">
      + Add
    </a>

Controller part:

$scope.getCode = function () {
  var code = 'javascript:(function(){s=document.createElement(\'SCRIPT\');s.type=\'text/javascript\';' +
    's.src=\'http://localhost:9000/scripts/bookmarklet/bookmarklet.js?x=' + ($scope.user.id) + '\';' +
    'document.getElementsByTagName(\'head\')[0].appendChild(s);document.sc_srvurl=\'http://localhost:8080\'})();'  ;
  return code;
};

But I get following after compilation:

<a class="bookmarklet" href="unsafe:javascript:(function(){s=document.createElement('SCRIPT');s.type='text/javascript';s.src='http://localhost:9000/scripts/bookmarklet/bookmarklet.js?x=5517325d40c37bc2bfe20db6';document.getElementsByTagName('head')[0].appendChild(s);document.sc_srvurl='http://localhost:8080'})();">
              + Add
            </a>

Link starts with "unsafe" and I can't get how to tell angular to trust this link.

This answer - Angular changes urls to "unsafe:" in extension page suggests to add protocol to whitelist. I don't want to disable $sce or adding "javascript" to whitelist protocols as I think it's insecure.

May I tell somehow to angularjs to avoid adding prefix "unsafe" by using $sce? Unfortunately documentation is not clear for me and $sce.trustAsJs(code) haven't helped me.

!EDIT Angular version is 1.4.1.

6
  • 1
    possible duplicate of Angular changes urls to "unsafe:" in extension page Commented Aug 12, 2015 at 15:42
  • The solution in stackoverflow.com/questions/15606751/… is to add protocol to whitelist, where I am concerned with security in my case. Commented Aug 12, 2015 at 15:53
  • I don't think you have any other options. And you wouldn't add 'javascript', you would add 'chrome-extension' to the whitelist. Commented Aug 12, 2015 at 16:06
  • That's a valid concern indeed. One alternative way I can think of is creating a directive and setting the value of the href attribute there (by manipulating it directly on the directive's DOM element). Is that feasible for your use case? Commented Aug 12, 2015 at 16:06
  • @plamut It's not clear for me how workaround with directive can help. I am wondering is there any direct way to tell angular to trust this url? Commented Aug 12, 2015 at 16:19

1 Answer 1

2

Try to circumvent the restrictions by writing a custom directive:

var app = angular.module('myApp', []);

app.directive('bookmarklet', function () {
    return {
        restrict: 'A',
        scope: {},
        link: function($scope, element, attrs) {
            if (element[0].tagName !== 'A') {
                return;  // simply do nothing (or raise an error)
            }
            element[0].href = 'javascript:alert("It works in 1.4.1, too!")';
        }
    };
 });

Usage:

<div ng-app="myApp">
    <a href="#foo" bookmarklet>click me</a>
</div>

I also created a fiddle demo to test it: http://jsfiddle.net/t0acdxcL/1/

Sign up to request clarification or add additional context in comments.

5 Comments

I have now fixed the link to the demo.
Thank you! I see that your fiddle works and there is clear 'javascript:alert("It works!")' without unsafe. However I tried it in my project and it still has unsafe href="unsafe:javascript:alert('It works!')". Wondering what is the difference.
I have updated angular dependency to 1.4.1 and it reproduces. See this fiddle - jsfiddle.net/ikaplin/8rm57bwf/2
I will add to question that angular version is 1.4.1
Updated my answer and the demo, it now works in 1.4.1, too. Seems like attrs.$set(...) behavior was changed at some point, but it's trivial to get around that. Setting the attribute value directly on the element does the trick, i.e. element[0].href = ....

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.