XSS issue in the angularjs application - angularjs

This is regarding injecting the script tag (given below) in one of the input and it's description field. Values are saving fine and showing in the grid.
Go to this <script>window.alert('abc')</script> and fill out the FAFSA.
Form fields:-
You can see in the below screenshot that the alert script is running from the description field.
Modal implementation (execute on click of the document type link in the listing):-
$rootScope.showNormalModal = function (message) {
var modalHtml = "<div class='modal-header'><button type='button' ng-click='cancel()' class='close' data-dismiss='modal' aria-label='Close'>" +
"<span aria-hidden='true'>×</span></button> " +
"<h4 class='modal-title' id='myModalLabel'><div>" +
"</div>" + message + "</h4></div>";
var modalInstance = $modal.open({
template: modalHtml,
controller: function ($scope, $modalInstance) {
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}
});
}
});
If the input parameter has script tag with some operation, it is not showing in the UI as it is, instead the script is running before the modal.
Expected behavior here is when I clicked on the anchor in the listing, it should show its description in the popup. what is happening here is, before showing the description, I am getting a alert window because of the script tag injection.
How will I avoid the alert script getting executed before the popup.
Attached all the screenshots below.
Listing Page :-
Alert Window :-
Description Popup :-
Thanks in advance.

Can you please try below code
$rootScope.showNormalModal = function (message) {
var modalHtml = "<div class='modal-header'><button type='button' ng-click='cancel()' class='close' data-dismiss='modal' aria-label='Close'>" +
"<span aria-hidden='true'>×</span></button> " +
"<h4 class='modal-title' id='myModalLabel'><div>" +
"</div><div ng-bind=\"message\"></div></h4></div>";
var modalInstance = $modal.open({
template: modalHtml,
controller: function ($scope, $modalInstance, message) {
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.message = message;
},
resolve: {
message: function () {
return message;
}
}
});
}

Related

On click event get selected value of google organization chart node in angularjs

I have created google organization chart in .Net MVC chart is displaying correctly. but i have to get some information on click event on chart node like their employee.id, employee.name.
I tried with below snippet code but however, it's not working.
google.visualization.events.addListener(chart1, 'ready', function () {
alert("3");
// grab a few details before redirecting
google.visualization.events.addListener(chart.getChart(), 'select', function () {
chartObject = chart.getChart();
alert(data.getValue(chartObject.getSelection()[0].row, 0));
});
});
In Below code how and where to add click event code?
var app = angular.module('myApp', []);
app.controller('myController', ['$scope', '$http', function ($scope, $http) {
//alert("dddd");
// window.alert("hi!");
//here http get method for get data from database
$scope.chartData = [['Name', 'ReportsTo', 'tooltip']];
$http.get('/home/getChartData').then(function (response) {
var newobject = [['Name', 'ReportsTo', 'tooltip']];
angular.forEach(response.data, function (val) {
newobject.push(
[
{
v: val.EmployeeID.toString(),
f: '<div class="customBox"><div>' + (val.FirstName + ' '
+ val.LastName) +
'</div><div class="title" id="' + val.EmployeeID + '">'
+ val.Title + '</div></div>'
},
(val.ReportsTo.toString() == "0" ? "" : val.ReportsTo.toString()),
(val.FirstName + ' ' + val.LastName)
]
);
})
$scope.chartData = newobject;
})
}])
app.directive('orgChart', function () {
function link($scope, element, attrs) {
var chart = new google.visualization.OrgChart(element[0]);
$scope.$watch('chartData', function (value, oldvalue) {
if (!value) {
return;
}
var data = google.visualization.arrayToDataTable(value);
var options = {
'title': '',
'allowHtml': true
}
chart.draw(data, options);
})
}
return {
link: link
};
})
Chart:- On Click first node i have to genrate click event.
the code you tried to implement is for a ChartWrapper,
you are using an OrgChart
var chart = new google.visualization.OrgChart(element[0]);
try the following, which should immediately follow the above line ^
google.visualization.events.addListener(chart, 'select', function () {
var selection = chart.getSelection();
if (selection.length > 0) {
alert(data.getValue(selection[0].row, 0));
}
});
note: be sure to check the length of the selection as above
the event will also fire when something is de-selected,
which will return an empty array,
causing this to fail --> selection[0].row

How to trigger mailto in AngularJS controller without changing window location

I have an angular controller that triggers a "mailto" link when a mail icon is clicked
angular
.module('app')
.component('header', {
template: '<i class="fa fa-envelope" aria-hidden="true"></i>',
controller: HeaderController,
controllerAs: 'headerCtrl'
});
function HeaderController() {
var vm = this;
vm.sendMail = sendMail;
function sendMail(response) {
var email = 'test#mail.com';
var subject = 'email%20subject';
var body = 'email%20body';
vm.mailToUri = 'mailto:' + email + '?subject=' + subject + '&body=' + body;
$window.location = vm.mailToUri;
}
}
Unfortunately, this is running in the same application as a directive that calls a logout url when the browser is closed
angular
.module('app')
.directive('onCloseLogout', onCloseLogout);
function onCloseLogout($http, $window) {
return {
restrict: 'AE',
link: function () {
$window.onbeforeunload = function () {
$http.get('/logout');
};
}
};
}
So, when the email link is clicked, the onCloseLogout directive is triggered, and the user is logged out.
Is there another way to open an email in angular, or to send a get request to the logout URL on browser close?
Turns out I had over engineered the solution. I added the mailToUri to the anchor tag as the ng-href attribute and it all works fine now
angular
.module('app')
.component('header', {
template: '<a ng-href="{{headerCtrl.mailToUri}}"><i class="fa fa-envelope" aria-hidden="true"></i></a>',
controller: HeaderController,
controllerAs: 'headerCtrl'
});
function HeaderController() {
var vm = this;
var email = 'test#mail.com';
var subject = 'email%20subject';
var body = 'email%20body';
vm.mailToUri = 'mailto:' + email + '?subject=' + subject + '&body=' + body;
}

Ionic + Angular ng-click not bind function from dynamic html element

I have an ion-list and I create each ion-item from a select statment. The ion-item tag has a ng-click event that call a modal window but it never call the show() method from controller. For test I put a static ion-item without DOM modification and it works well.
This is the code:
Modal controller
function uib_w_27_modal_controller($scope, $ionicModal) {
$scope.modal = $ionicModal.fromTemplate($(".uib_w_27").html(), {
scope: $scope,
animation: 'slide-in-up'
});
$scope.show = function() {
$scope.modal.show();
};
$scope.close = function() {
$scope.modal.hide();
};
//Cleanup the modal when we're done with it!
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
// Execute action on hide modal
$scope.$on('modal.hidden', function() {
// Execute action
});
// Execute action on remove modal
$scope.$on('modal.removed', function() {
// Execute action
});
};
Dynamic element
function getFarmaciasSelect(tx, result){
var elem = '';
for (var i = 0; i < result.rows.length; i++) {
var row = result.rows.item(i);
elem += '<ion-item class="item widget uib_w_24 d-margins item-avatar item-icon-right" data-uib="ionic/list_item_avatar" data-ver="0">' +
'<img src="images/Strabburg.jpg">' +
'<h2>' + row['nombre'] + '</h2>' +
'<p>' + row['calle'] + ' ' + row['altura'] + '</p>' +
'<a href="tel:' + row['fijo'] + '"style="text-decoration:none;color:#4CAF50" >' + row['fijo'] + '</a>' +
'<i class="icon ion-plus-circled ion" uib-icon-position="right" ng-controller="uib_w_27_modal_controller" ng-click="show()" data-email="email#email.com"></i>' +
'</ion-item>';
console.log(elem);
}
$('#farmacias-list').html(elem);
}
Thanks for help!
If you really need to keep generating in your code then you need compile your content before add to '#farmacias-list'
$('#farmacias-list').html($compile(elem)($scope));
but even it work, I will recommend you to use collection-repeat to generate content in angular context.

Using ui-router with Bootstrap-ui modal

I know this has been covered many times and most articles refer to this bit of code: Modal window with custom URL in AngularJS
But I just don't get it. I don't find that to be very clear at all. I also found this jsfiddle which was actually great, very helpful except this doesn't add the url and allow for me to use the back button to close the modal.
Edit: This is what I need help with.
So let me try explain what I am trying to achieve. I have a form to add a new item, and I have a link 'add new item'. I would like when I click 'add new item' a modal pops up with the form I have created 'add-item.html'. This is a new state so the url changes to /add-item.
I can fill out the form and then choose to save or close. Close, closes the modal :p (how odd) . But I can also click back to close the modal as well and return to the previous page(state).
I don't need help with Close at this point as I am still struggling with actually getting the modal working.
This is my code as it stands:
Navigation Controller: (is this even the correct place to put the modal functions?)
angular.module('cbuiRouterApp')
.controller('NavbarCtrl', function ($scope, $location, Auth, $modal) {
$scope.menu = [{
'title': 'Home',
'link': '/'
}];
$scope.open = function(){
// open modal whithout changing url
$modal.open({
templateUrl: 'components/new-item/new-item.html'
});
// I need to open popup via $state.go or something like this
$scope.close = function(result){
$modal.close(result);
};
};
$scope.isCollapsed = true;
$scope.isLoggedIn = Auth.isLoggedIn;
$scope.isAdmin = Auth.isAdmin;
$scope.getCurrentUser = Auth.getCurrentUser;
$scope.logout = function() {
Auth.logout();
$location.path('/login');
};
$scope.isActive = function(route) {
return route === $location.path();
};
});
This is how I am activating the modal:
<li ng-show='isLoggedIn()' ng-class='{active: isActive("/new-item")}'>
<a href='javascript: void 0;' ng-click='open()'>New Item</a>
</li>
new-item.html:
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<ul>
<li ng-repeat="item in items"><a ng-click="selected.item = item">{{ item }}</a></li>
</ul>Selected:<b>{{ selected.item }}</b>
</div>
<div class="modal-footer">
<button ng-click="ok()" class="btn btn-primary">OK</button>
<button ng-click="close()" class="btn btn-primary">OK</button>
</div>
Also whilst this does open a modal it doesn't close it as I couldn't work that out.
It's intuitive to think of a modal as the view component of a state. Take a state definition with a view template, a controller and maybe some resolves. Each of those features also applies to the definition of a modal. Go a step further and link state entry to opening the modal and state exit to closing the modal, and if you can encapsulate all of the plumbing then you have a mechanism that can be used just like a state with ui-sref or $state.go for entry and the back button or more modal-specific triggers for exit.
I've studied this fairly extensively, and my approach was to create a modal state provider that could be used analogously to $stateProvider when configuring a module to define states that were bound to modals. At the time, I was specifically interested in unifying control over modal dismissal through state and modal events which gets more complicated than what you're asking for, so here is a simplified example.
The key is making the modal the responsibility of the state and using hooks that modal provides to keep the state in sync with independent interactions that modal supports through the scope or its UI.
.provider('modalState', function($stateProvider) {
var provider = this;
this.$get = function() {
return provider;
}
this.state = function(stateName, options) {
var modalInstance;
$stateProvider.state(stateName, {
url: options.url,
onEnter: function($modal, $state) {
modalInstance = $modal.open(options);
modalInstance.result['finally'](function() {
modalInstance = null;
if ($state.$current.name === stateName) {
$state.go('^');
}
});
},
onExit: function() {
if (modalInstance) {
modalInstance.close();
}
}
});
};
})
State entry launches the modal. State exit closes it. The modal might close on its own (ex: via backdrop click), so you have to observe that and update the state.
The benefit of this approach is that your app continues to interact mainly with states and state-related concepts. If you later decide to turn the modal into a conventional view or vice-versa, then very little code needs to change.
Here is a provider that improves #nathan-williams solution by passing resolve section down to the controller:
.provider('modalState', ['$stateProvider', function($stateProvider) {
var provider = this;
this.$get = function() {
return provider;
}
this.state = function(stateName, options) {
var modalInstance;
options.onEnter = onEnter;
options.onExit = onExit;
if (!options.resolve) options.resolve = [];
var resolveKeys = angular.isArray(options.resolve) ? options.resolve : Object.keys(options.resolve);
$stateProvider.state(stateName, omit(options, ['template', 'templateUrl', 'controller', 'controllerAs']));
onEnter.$inject = ['$uibModal', '$state', '$timeout'].concat(resolveKeys);
function onEnter($modal, $state, $timeout) {
options.resolve = {};
for (var i = onEnter.$inject.length - resolveKeys.length; i < onEnter.$inject.length; i++) {
(function(key, val) {
options.resolve[key] = function() { return val }
})(onEnter.$inject[i], arguments[i]);
}
$timeout(function() { // to let populate $stateParams
modalInstance = $modal.open(options);
modalInstance.result.finally(function() {
$timeout(function() { // to let populate $state.$current
if ($state.$current.name === stateName)
$state.go(options.parent || '^');
});
});
});
}
function onExit() {
if (modalInstance)
modalInstance.close();
}
return provider;
}
}]);
function omit(object, forbidenKeys) {
var prunedObject = {};
for (var key in object)
if (forbidenKeys.indexOf(key) === -1)
prunedObject[key] = object[key];
return prunedObject;
}
then use it like that:
.config(['modalStateProvider', function(modalStateProvider) {
modalStateProvider
.state('...', {
url: '...',
templateUrl: '...',
controller: '...',
resolve: {
...
}
})
}]);
I answered a similar question, and provided an example here:
Modal window with custom URL in AngularJS
Has a complete working HTML and a link to plunker.
The $modal itself doesn't have a close() funcftion , I mean If you console.log($modal) , You can see that there is just an open() function.
Closing the modal relies on $modalInstance object , that you can use in your modalController.
So This : $modal.close(result) is not actually a function!
Notice :
console.log($modal);
==>> result :
Object { open: a.$get</k.open() }
// see ? just open ! , no close !
There is some way to solve this , one way is :
First you must define a controller in your modal like this :
$modal.open({
templateUrl: 'components/new-item/new-item.html',
controller:"MyModalController"
});
And then , Later on , :
app.controller('MyModalController',function($scope,$modalInstance){
$scope.closeMyModal = function(){
$modalInstance.close(result);
}
// Notice that, This $scope is a seperate scope from your NavbarCtrl,
// If you want to have that scope here you must resolve it
});

Angularjs Hash linking redirects to a new URL

I want to link to an element on the same page. I followed the link below but for some reason it redirecting me to the same URL with #id attached to the URL, I have html5Mode enabled.
How to handle anchor hash linking in AngularJS
directive code
var commonComponentsApp = commonComponentsApp || angular.module('cpUtils', []);
commonComponentsApp.directive("highlight", function ($location, $compile, $anchorScroll) {
'use strict';
return {
restrict: "A",
controller: function ($scope) {
$scope.scrollTo = function (id) {
console.log(id);
$location.hash(id);
$anchorScroll();
}
},
link: function (scope, element, attrs) {
var hightedText = attrs.highlight;
hightedText = hightedText.replace("<em", "<em ng-click=scrollTo('" + attrs.id + "')");
var item = '<p>' + hightedText + '</p>';
var e = angular.element(item);
e = $compile(e)(scope);
element.html(e);
}
};
});
Any help will be much appreciated. Thanks
UPDATE
Its inside a ng-repeaet
<li id="document-{{$index}}" ng-repeat="document in query.response.result" ng- mouseenter="select(document, $index)" bubble>
<div class="description-wrapper">
......
<hr />
<p highlight="{{query.response.highlighted[document.id].text[0]}}" id="{{document.id}}"></p>
.....
</div>
</li>
as you hover over a list item, it shows the complete record on the side which has the link it should scroll to.
Does your attrs.id value contain the hash? If so, it shouldn't. You only need the id value, without the hash.
Also, your ng-click=scrollTo(id) is missing quotes:
<em ng-click="scrollTo('idName')">

Resources