I am building a site that illustrates common application vulnerabilities such as SQL Injection. I am using AngularJS and highlight.js to create interactive examples.
How can I make both AngularJS and highlight.js update my code snippets?
Example
This Fiddle demonstrates how entering ' OR 1=1 --
in the Email field could change the intended behavior of the query if the user's input is not validated or sanitized.
SELECT * FROM dbo.Users WHERE Email='{{email}}' AND Password='{{password}}'
When a user enters an email address and password, Angular updates the query. However, syntax highlighting does not update.
SELECT * FROM dbo.Users WHERE Email='[email protected]' AND Password=''
I tried re-initializing hljs, but when I do angular stops updating the query.
hljs.initHighlighting.called = false;
hljs.initHighlighting();
Application
<script>
var app = angular.module("app", ['hljs']);
app.controller("controller", function($scope) {
$scope.email = "[email protected]";
$scope.password = "";
})
</script>
<div ng-app="app" ng-controller="controller">
<div>
<div class="row">
<div class="col-sm-4">Email
<input type="text" class="form-control" ng-model="email">
</div>
<div class="col-sm-4">Password
<input type="text" class="form-control" ng-model="password">
</div>
</div>
<br>
<div hljs include="'compile-me'" compile="true" language="sql"></div>
</div>
<script type="text/ng-template" id="compile-me">
SELECT * FROM dbo.Users WHERE Email = '{{email}}'
AND Password = '{{password}}'
</script>
</div>
I am building a site that illustrates common application vulnerabilities such as SQL Injection. I am using AngularJS and highlight.js to create interactive examples.
How can I make both AngularJS and highlight.js update my code snippets?
Example
This Fiddle demonstrates how entering ' OR 1=1 --
in the Email field could change the intended behavior of the query if the user's input is not validated or sanitized.
SELECT * FROM dbo.Users WHERE Email='{{email}}' AND Password='{{password}}'
When a user enters an email address and password, Angular updates the query. However, syntax highlighting does not update.
SELECT * FROM dbo.Users WHERE Email='[email protected]' AND Password=''
I tried re-initializing hljs, but when I do angular stops updating the query.
hljs.initHighlighting.called = false;
hljs.initHighlighting();
Application
<script>
var app = angular.module("app", ['hljs']);
app.controller("controller", function($scope) {
$scope.email = "[email protected]";
$scope.password = "";
})
</script>
<div ng-app="app" ng-controller="controller">
<div>
<div class="row">
<div class="col-sm-4">Email
<input type="text" class="form-control" ng-model="email">
</div>
<div class="col-sm-4">Password
<input type="text" class="form-control" ng-model="password">
</div>
</div>
<br>
<div hljs include="'compile-me'" compile="true" language="sql"></div>
</div>
<script type="text/ng-template" id="compile-me">
SELECT * FROM dbo.Users WHERE Email = '{{email}}'
AND Password = '{{password}}'
</script>
</div>
Share
Improve this question
asked Aug 30, 2014 at 10:52
Mark GoodMark Good
4,3032 gold badges34 silver badges49 bronze badges
2 Answers
Reset to default 8In the jsfiddle you have provided you're using angular-highlightjs which in your case basically:
- Fetches the template you have provided with
include
directive applies - Invokes highlightjs library API on the template which produces HTML markup with highlighted elements having correct style for particular language
- The highlighted HTML markup is then passed over to angularjs
$compile
Afterwards no highglighting takes place - in particular even when interpolated content changes.
One way to solve it is to use source
directive from angular-highlightjs
which is observed but I think it's simpler to build a custom directive.
The trick here is to manually interpolate and highlight content. I've updated your fiddle with a simplistic highlight
directive that presents the idea:
app.directive('highlight', function($interpolate, $window){
return {
restrict: 'EA',
scope: true,
compile: function (tElem, tAttrs) {
var interpolateFn = $interpolate(tElem.html(), true);
tElem.html(''); // stop automatic intepolation
return function(scope, elem, attrs){
scope.$watch(interpolateFn, function (value) {
elem.html(hljs.highlight('sql',value).value);
});
}
}
};
});
A simpler way I just found is to use a filter:
app.filter('highlight', function($sce) {
return function(input, lang) {
if (lang && input) return hljs.highlight(lang, input).value;
return input;
}
}).filter('unsafe', function($sce) { return $sce.trustAsHtml; })
Then you can say:
<pre><code ng-bind-html="someScopeVariable | highlight | unsafe"></code></pre>
The $sce needs to be injected into your app, and tells Angular to display the HTML raw - that you trust it.