aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/content/error/parse/isecdom.ngdoc16
-rw-r--r--docs/content/error/parse/isecwindow.ngdoc16
-rw-r--r--src/ng/parse.js15
-rw-r--r--test/ng/parseSpec.js215
4 files changed, 175 insertions, 87 deletions
diff --git a/docs/content/error/parse/isecdom.ngdoc b/docs/content/error/parse/isecdom.ngdoc
new file mode 100644
index 00000000..666bf36c
--- /dev/null
+++ b/docs/content/error/parse/isecdom.ngdoc
@@ -0,0 +1,16 @@
+@ngdoc error
+@name $parse:isecdom
+@fullName Referencing a DOM node in Expression
+@description
+
+Occurs when an expression attempts to access a DOM node.
+
+AngularJS restricts access to DOM nodes from within expressions since it's a known way to
+execute arbitrary Javascript code.
+
+This check is only performed on object index and function calls in Angular expressions. These are
+places that are harder for the developer to guard. Dotted member access (such as a.b.c) does not
+perform this check - it's up to the developer to not expose such sensitive and powerful objects
+directly on the scope chain.
+
+To resolve this error, avoid access to DOM nodes.
diff --git a/docs/content/error/parse/isecwindow.ngdoc b/docs/content/error/parse/isecwindow.ngdoc
new file mode 100644
index 00000000..81adeea0
--- /dev/null
+++ b/docs/content/error/parse/isecwindow.ngdoc
@@ -0,0 +1,16 @@
+@ngdoc error
+@name $parse:isecwindow
+@fullName Referencing Window object in Expression
+@description
+
+Occurs when an expression attempts to access a Window object.
+
+AngularJS restricts access to the Window object from within expressions since it's a known way to
+execute arbitrary Javascript code.
+
+This check is only performed on object index and function calls in Angular expressions. These are
+places that are harder for the developer to guard. Dotted member access (such as a.b.c) does not
+perform this check - it's up to the developer to not expose such sensitive and powerful objects
+directly on the scope chain.
+
+To resolve this error, avoid Window access.
diff --git a/src/ng/parse.js b/src/ng/parse.js
index 5597acd8..8f8c0f87 100644
--- a/src/ng/parse.js
+++ b/src/ng/parse.js
@@ -42,12 +42,20 @@ function ensureSafeObject(obj, fullExpression) {
if (obj && obj.constructor === obj) {
throw $parseMinErr('isecfn',
'Referencing Function in Angular expressions is disallowed! Expression: {0}', fullExpression);
+ //
+ } else if (// isWindow(obj)
+ obj && obj.document && obj.location && obj.alert && obj.setInterval) {
+ throw $parseMinErr('isecwindow',
+ 'Referencing the Window in Angular expressions is disallowed! Expression: {0}', fullExpression);
+ } else if (// isElement(obj)
+ obj && (obj.nodeName || (obj.on && obj.find))) {
+ throw $parseMinErr('isecdom',
+ 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}', fullExpression);
} else {
return obj;
}
}
-
var OPERATORS = {
'null':function(){return null;},
'true':function(){return true;},
@@ -688,6 +696,9 @@ function parser(text, json, $filter, csp){
args.push(argsFn[i](scope, locals));
}
var fnPtr = fn(scope, locals, context) || noop;
+
+ ensureSafeObject(fnPtr, text);
+
// IE stupidity!
var v = fnPtr.apply
? fnPtr.apply(context, args)
@@ -703,7 +714,7 @@ function parser(text, json, $filter, csp){
v = v.$$v;
}
- return v;
+ return ensureSafeObject(v, text);
};
}
diff --git a/test/ng/parseSpec.js b/test/ng/parseSpec.js
index a82f736f..44b648c5 100644
--- a/test/ng/parseSpec.js
+++ b/test/ng/parseSpec.js
@@ -555,100 +555,145 @@ describe('parser', function() {
});
describe('sandboxing', function() {
- it('should NOT allow access to Function constructor in getter', function() {
- expect(function() {
- scope.$eval('{}.toString.constructor');
- }).toThrowMinErr(
- '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
- 'Expression: {}.toString.constructor');
-
- expect(function() {
- scope.$eval('{}.toString.constructor("alert(1)")');
- }).toThrowMinErr(
- '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
- 'Expression: {}.toString.constructor("alert(1)")');
-
- expect(function() {
- scope.$eval('[].toString.constructor.foo');
- }).toThrowMinErr(
- '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
- 'Expression: [].toString.constructor.foo');
-
- expect(function() {
- scope.$eval('{}.toString["constructor"]');
- }).toThrowMinErr(
- '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
- 'Expression: {}.toString["constructor"]');
- expect(function() {
- scope.$eval('{}["toString"]["constructor"]');
- }).toThrowMinErr(
- '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
- 'Expression: {}["toString"]["constructor"]');
-
- scope.a = [];
- expect(function() {
- scope.$eval('a.toString.constructor', scope);
- }).toThrowMinErr(
- '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
- 'Expression: a.toString.constructor');
- expect(function() {
- scope.$eval('a.toString["constructor"]', scope);
- }).toThrowMinErr(
- '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
- 'Expression: a.toString["constructor"]');
- });
-
- it('should NOT allow access to Function constructor in setter', function() {
- expect(function() {
- scope.$eval('{}.toString.constructor = 1');
- }).toThrowMinErr(
- '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
- 'Expression: {}.toString.constructor = 1');
+ describe('Function constructor', function() {
+ it('should NOT allow access to Function constructor in getter', function() {
+ expect(function() {
+ scope.$eval('{}.toString.constructor');
+ }).toThrowMinErr(
+ '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
+ 'Expression: {}.toString.constructor');
+
+ expect(function() {
+ scope.$eval('{}.toString.constructor("alert(1)")');
+ }).toThrowMinErr(
+ '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
+ 'Expression: {}.toString.constructor("alert(1)")');
+
+ expect(function() {
+ scope.$eval('[].toString.constructor.foo');
+ }).toThrowMinErr(
+ '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
+ 'Expression: [].toString.constructor.foo');
+
+ expect(function() {
+ scope.$eval('{}.toString["constructor"]');
+ }).toThrowMinErr(
+ '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
+ 'Expression: {}.toString["constructor"]');
+ expect(function() {
+ scope.$eval('{}["toString"]["constructor"]');
+ }).toThrowMinErr(
+ '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
+ 'Expression: {}["toString"]["constructor"]');
+
+ scope.a = [];
+ expect(function() {
+ scope.$eval('a.toString.constructor', scope);
+ }).toThrowMinErr(
+ '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
+ 'Expression: a.toString.constructor');
+ expect(function() {
+ scope.$eval('a.toString["constructor"]', scope);
+ }).toThrowMinErr(
+ '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
+ 'Expression: a.toString["constructor"]');
+ });
- expect(function() {
- scope.$eval('{}.toString.constructor.a = 1');
- }).toThrowMinErr(
- '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
- 'Expression: {}.toString.constructor.a = 1');
+ it('should NOT allow access to Function constructor in setter', function() {
+ expect(function() {
+ scope.$eval('{}.toString.constructor = 1');
+ }).toThrowMinErr(
+ '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
+ 'Expression: {}.toString.constructor = 1');
+
+ expect(function() {
+ scope.$eval('{}.toString.constructor.a = 1');
+ }).toThrowMinErr(
+ '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
+ 'Expression: {}.toString.constructor.a = 1');
+
+ expect(function() {
+ scope.$eval('{}.toString["constructor"]["constructor"] = 1');
+ }).toThrowMinErr(
+ '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
+ 'Expression: {}.toString["constructor"]["constructor"] = 1');
+
+
+ scope.key1 = "const";
+ scope.key2 = "ructor";
+ expect(function() {
+ scope.$eval('{}.toString[key1 + key2].foo = 1');
+ }).toThrowMinErr(
+ '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
+ 'Expression: {}.toString[key1 + key2].foo = 1');
+
+ expect(function() {
+ scope.$eval('{}.toString["constructor"]["a"] = 1');
+ }).toThrowMinErr(
+ '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
+ 'Expression: {}.toString["constructor"]["a"] = 1');
+
+ scope.a = [];
+ expect(function() {
+ scope.$eval('a.toString.constructor = 1', scope);
+ }).toThrowMinErr(
+ '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
+ 'Expression: a.toString.constructor = 1');
+ });
- expect(function() {
- scope.$eval('{}.toString["constructor"]["constructor"] = 1');
- }).toThrowMinErr(
- '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
- 'Expression: {}.toString["constructor"]["constructor"] = 1');
+ it('should NOT allow access to Function constructor that has been aliased', function() {
+ scope.foo = { "bar": Function };
+ expect(function() {
+ scope.$eval('foo["bar"]');
+ }).toThrowMinErr(
+ '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
+ 'Expression: foo["bar"]');
- scope.key1 = "const";
- scope.key2 = "ructor";
- expect(function() {
- scope.$eval('{}.toString[key1 + key2].foo = 1');
- }).toThrowMinErr(
- '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
- 'Expression: {}.toString[key1 + key2].foo = 1');
+ });
- expect(function() {
- scope.$eval('{}.toString["constructor"]["a"] = 1');
- }).toThrowMinErr(
- '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
- 'Expression: {}.toString["constructor"]["a"] = 1');
- scope.a = [];
- expect(function() {
- scope.$eval('a.toString.constructor = 1', scope);
- }).toThrowMinErr(
- '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
- 'Expression: a.toString.constructor = 1');
+ it('should NOT allow access to Function constructor in getter', function() {
+ expect(function() {
+ scope.$eval('{}.toString.constructor');
+ }).toThrowMinErr(
+ '$parse', 'isecfld', 'Referencing "constructor" field in Angular expressions is disallowed! ' +
+ 'Expression: {}.toString.constructor');
+ });
});
- it('should NOT allow access to Function constructor that has been aliased', function() {
- scope.foo = { "bar": Function };
- expect(function() {
- scope.$eval('foo["bar"]');
- }).toThrowMinErr(
- '$parse', 'isecfn', 'Referencing Function in Angular expressions is disallowed! ' +
- 'Expression: foo["bar"]');
-
+ describe('Window and $element/node', function() {
+ it('should NOT allow access to the Window or DOM when indexing', inject(function($window, $document) {
+ scope.wrap = {w: $window, d: $document};
+
+ expect(function() {
+ scope.$eval('wrap["w"]', scope);
+ }).toThrowMinErr(
+ '$parse', 'isecwindow', 'Referencing the Window in Angular expressions is ' +
+ 'disallowed! Expression: wrap["w"]');
+ expect(function() {
+ scope.$eval('wrap["d"]', scope);
+ }).toThrowMinErr(
+ '$parse', 'isecdom', 'Referencing DOM nodes in Angular expressions is ' +
+ 'disallowed! Expression: wrap["d"]');
+ }));
+
+ it('should NOT allow access to the Window or DOM returned from a function', inject(function($window, $document) {
+ scope.getWin = valueFn($window);
+ scope.getDoc = valueFn($document);
+
+ expect(function() {
+ scope.$eval('getWin()', scope);
+ }).toThrowMinErr(
+ '$parse', 'isecwindow', 'Referencing the Window in Angular expressions is ' +
+ 'disallowed! Expression: getWin()');
+ expect(function() {
+ scope.$eval('getDoc()', scope);
+ }).toThrowMinErr(
+ '$parse', 'isecdom', 'Referencing DOM nodes in Angular expressions is ' +
+ 'disallowed! Expression: getDoc()');
+ }));
});
});