I'm working on a CMS driven website using Angular (1.2 RC2) on the client side. As the content comes from a CMS I'm unfortunately forced to use receive HTML in JSON Strings. Most of the HTML gets injected and rendered just fine, but image tags have their src stripped away. From what I've read the src should have been prefixed with "unsafe:", not removed entirely if this was a XSS security issue in Angular .. but I might be mistaken.
I've been at this problem for a while now and feel I've tried everything from plausible to downright stupid. Whitelisting my CMS url, whitelisting everything, disabling $sce, forcing html trough $sce.trustAsHtml() and well ... So far, no luck. As the site is CMS driven I'm unfortunatly not able to create a plunker / fiddle, but I'm hoping a kind soul will try to help out anyway.
Update: Forgot to mention that I've also tried ng-src, same effect. Update II: If I use a HTTPS the src attribute remains and the image is shown. This is acceptable as it will run on HTTPS in production, but I still would like to know why disabling $sce doesn't work.
HTML as seen by the browser (content of slide.body)
<div class="row">
<div class="col-md-6 visible-md visible-lg">
<img alt="none" class="img-responsive">
</div>
<div class="col-xs-12 col-md-6">
<div class="itx-article-header">
<h1>Sulvat Quis 1</h1>
<h2>– Nullam dictum ac enim</h2>
</div>
<p>Proin quis justo vel felis varius sodales sit amet ut diam.</p>
</div>
</div>
JADE (HTML)
.my-carousel(ng-controller='CarouselCtrl')
carousel(interval='myInterval')
slide(ng-repeat='slide in slides', active='slide.active')
.my-carousel-item(ng-bind-html='slide.body')
Angular Controller
.controller('CarouselCtrl', ['$sce', 'Article', '$scope',
function($sce, Article, $scope) {
$scope.myInterval = -1;
$scope.slides = Article.query(
{category: 'carousel'},
function(data){
for (var i = 0; i < data.length; i++) {
$scope.slides[i].body = $sce.trustAsHtml(data[i].body);
}
},
function() {
// Fail
});
}])
Example JSON Response (Slide) Sorry about the wide box, didn't manage to format it.
{
"cmarId": 16,
"corp": {
"corpId": 2,
"guiSelected": false
},
"createdAt": "Sep 27, 2013",
"articleTag": "slide-1",
"headline": "Slide 1",
"highlighted": false,
"body": "\u003cdiv class\u003d\"container my-carousel-container-small\"\u003e\r\n\u003cdiv class\u003d\"row\"\u003e\r\n\u003cdiv class\u003d\"col-md-6 visible-md visible-lg\"\u003e\u003cimg ng-src\u003d\"img/illustrative/laptop.jpg\" alt\u003d\"none\" class\u003d\"img-responsive\" /\u003e\u003c/div\u003e\r\n\u003cdiv class\u003d\"col-xs-12 col-md-6\"\u003e\r\n\u003cdiv class\u003d\"my-article-header\"\u003e\r\n\u003ch1\u003eSulvat Quis 1\u003c/h1\u003e\r\n\u003ch2\u003e– Nullam dictum ac enim\u003c/h2\u003e\r\n\u003c/div\u003e\r\n\u003cp\u003eProin quis justo vel felis varius sodales sit amet ut diam. Fusce auctor sapien nec purus sagittis, in venenatis turpis luctus. Nullam dictum ac enim sed commodo. Vivamus et placerat sapien.\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e",
"articlePriority": 0,
"category": {
"cmcaId": 9,
"corp": {
"corpId": 2,
"guiSelected": false
},
"name": "carousel",
"visibleInMenu": false
},
"published": true
}