Using Angular and a Content Security Policy? Watch out for this...

Edit on July 6, 2015: Kevin H, in the comments below, pointed out that the docs for ngShow actually talk about this! I missed this completely. The solution the docs recommend, including an additional CSS file, worked fine for me, and feels like a "better" solution than mine, so I recommend following the docs lead.

I’ve been working on a Cordova app that uses AngularJS. It has been working fine for a while now but I needed to do a bit of cleanup. After I pushed up my changes, my client noticed something odd. We have a button that only shows up under certain situations. Basically, if some scope variable is true, we display it.

<button ng-show="featureEnabled">Feature</button>

All of a sudden, the button began showing up in all cases, even when the variable was false. I began to debug. I double checked to ensure my variable wasn’t being set true when it shouldn’t be. That wasn’t the problem. I then added some simple tests to my view.

first test, <span ng-show="!barcodeAllowed.status">DONT SHOW</span><br/>
second test, <span ng-show="barcodeAllowed.status == false">DONT SHOW</span><br/>
test -{{barcodeAllowed.status}}-end -{{!barcodeAllowed.status}}- -{{barcodeAllowed | json}}-<br/>
test if <span ng-if="barcodeAllowed.status"> if was true</span><br/>
test opp if <span ng-if="!barcodeAllowed.status"> will see it</span>

As you can see, I checked both the negation of the variable an the variable itself. I also output it, and the negation, as well as the JSON version of the variable. Finally I did two tests using ng-if.

Here is where things got freaky. Both of the first two ng-show tests showed up! Even though the value in the third line was exactly what I expected - false.

And to make things even more weird - the ng-if’s worked perfectly! At this point, I was just considering switching to ng-if, but then I punted and asked over on StackOverflow. I had a long “conversation” with user thsorens and he reminded me that ng-show/ng-hide will add/remove CSS classes based on the condition.

Then I paused and thought a bit. When I did my ‘cleanup’ of the app, I made a few different changes. For example, I had been using a remote Angular JS library and I switched it to a local one. I double checked to ensure it wasn’t a version issue. I also made use of a Content Security Policy. I talked about this on my blog a few months ago. As a reminder, it is a way to lock down the resources your Cordova app, or any web app, can make use of. On a whim, I renamed the meta tag that defined the CSP and bammo - things worked!

I didn’t want to just remove the CSP, so I dug a bit deeper. It occurred to me that JavaScript was being used to create and manipulate CSS, so I looked at the script-src I had defined:

script-src 'self'

I then though… I bet Angular is using eval. So I added this:

script-src 'self' 'unsafe-eval'

And that did it. Here is a code sample that demonstrates the issue. First, the HTML:

<!DOCTYPE html>
<html ng-app="plunker">
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">