Skip to content

Commit db713a1

Browse files
rodyhaddadIgorMinar
authored andcommitted
refactor($parse): move around previous security changes made to $parse
1 parent 6081f20 commit db713a1

File tree

4 files changed

+146
-204
lines changed

4 files changed

+146
-204
lines changed
Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
@ngdoc error
22
@name $parse:isecfld
3-
@fullName Referencing 'constructor' Field in Expression
3+
@fullName Referencing Disallowed Field in Expression
44
@description
55

6-
Occurs when an expression attempts to access an objects constructor field.
6+
Occurs when an expression attempts to access one of the following fields:
77

8-
AngularJS bans constructor access from within expressions since constructor
9-
access is a known way to execute arbitrary Javascript code.
8+
* __proto__
9+
* __defineGetter__
10+
* __defineSetter__
11+
* __lookupGetter__
12+
* __lookupSetter__
1013

11-
To resolve this error, avoid constructor access. As a last resort, alias
12-
the constructor and access it through the alias instead.
14+
AngularJS bans access to these fields from within expressions since
15+
access is a known way to mess with native objects or
16+
to execute arbitrary Javascript code.
1317

14-
Example expression that would result in this error:
18+
To resolve this error, avoid using these fields in expressions. As a last resort,
19+
alias their value and access them through the alias instead.
20+
21+
Example expressions that would result in this error:
1522

1623
```
17-
<div>{{user.constructor.name}}</div>
18-
```
24+
<div>{{user.__proto__.hasOwnProperty = $emit}}</div>
25+
26+
<div>{{user.__defineGetter__('name', noop)}}</div>
27+
```
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
@ngdoc error
2+
@name $parse:isecobj
3+
@fullName Referencing Object Disallowed
4+
@description
5+
6+
Occurs when an expression attempts to access the 'Object' object (Root object in JavaScript).
7+
8+
Angular bans access to Object from within expressions since access is a known way to modify
9+
the behaviour of existing objects.
10+
11+
To resolve this error, avoid Object access.

src/ng/parse.js

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,39 +10,26 @@ var $parseMinErr = minErr('$parse');
1010
//
1111
// As an example, consider the following Angular expression:
1212
//
13-
// {}.toString.constructor(alert("evil JS code"))
14-
//
15-
// We want to prevent this type of access. For the sake of performance, during the lexing phase we
16-
// disallow any "dotted" access to any member named "constructor".
17-
//
18-
// For reflective calls (a[b]) we check that the value of the lookup is not the Function constructor
19-
// while evaluating the expression, which is a stronger but more expensive test. Since reflective
20-
// calls are expensive anyway, this is not such a big deal compared to static dereferencing.
13+
// {}.toString.constructor('alert("evil JS code")')
2114
//
2215
// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
2316
// against the expression language, but not to prevent exploits that were enabled by exposing
2417
// sensitive JavaScript or browser apis on Scope. Exposing such objects on a Scope is never a good
2518
// practice and therefore we are not even trying to protect against interaction with an object
2619
// explicitly exposed in this way.
2720
//
28-
// A developer could foil the name check by aliasing the Function constructor under a different
29-
// name on the scope.
30-
//
3121
// In general, it is not possible to access a Window object from an angular expression unless a
3222
// window or some DOM object that has a reference to window is published onto a Scope.
23+
// Similarly we prevent invocations of function known to be dangerous, as well as assignments to
24+
// native objects.
25+
3326

3427
function ensureSafeMemberName(name, fullExpression) {
35-
if (name === "constructor") {
28+
if (name === "__defineGetter__" || name === "__defineSetter__"
29+
|| name === "__lookupGetter__" || name === "__lookupSetter__"
30+
|| name === "__proto__") {
3631
throw $parseMinErr('isecfld',
37-
'Referencing "constructor" field in Angular expressions is disallowed! Expression: {0}',
38-
fullExpression);
39-
} else if (name === "__defineGetter__" || name === "__defineSetter__"
40-
|| name === "__lookupGetter__" || name === "__lookupSetter__") {
41-
throw $parseMinErr('isecgetset',
42-
'Defining and looking up getters and setters in Angular expressions is disallowed! '
43-
+'Expression: {0}', fullExpression);
44-
} else if (name === "__proto__") {
45-
throw $parseMinErr('isecproto', 'Using __proto__ in Angular expressions is disallowed! '
32+
'Attempting to access a disallowed field in Angular expressions! '
4633
+'Expression: {0}', fullExpression);
4734
}
4835
return name;
@@ -56,7 +43,7 @@ function ensureSafeObject(obj, fullExpression) {
5643
'Referencing Function in Angular expressions is disallowed! Expression: {0}',
5744
fullExpression);
5845
} else if (// isWindow(obj)
59-
obj.document && obj.location && obj.alert && obj.setInterval) {
46+
obj.window === obj) {
6047
throw $parseMinErr('isecwindow',
6148
'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
6249
fullExpression);
@@ -65,21 +52,26 @@ function ensureSafeObject(obj, fullExpression) {
6552
throw $parseMinErr('isecdom',
6653
'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
6754
fullExpression);
68-
} else if (// isObject(obj)
69-
obj.getOwnPropertyNames || obj.getOwnPropertyDescriptor) {
55+
} else if (// block Object so that we can't get hold of dangerous Object.* methods
56+
obj === Object) {
7057
throw $parseMinErr('isecobj',
7158
'Referencing Object in Angular expressions is disallowed! Expression: {0}',
7259
fullExpression);
73-
} else if (obj === ({}).__defineGetter__ || obj === ({}).__defineSetter__
74-
|| obj === ({}).__lookupGetter__ || obj === ({}).__lookupSetter__) {
75-
throw $parseMinErr('isecgetset',
76-
'Defining and looking up getters and setters in Angular expressions is disallowed! '
77-
+'Expression: {0}', fullExpression);
7860
}
7961
}
8062
return obj;
8163
}
8264

65+
function ensureSafeFunction(obj, fullExpression) {
66+
if (obj) {
67+
if (obj.constructor === obj) {
68+
throw $parseMinErr('isecfn',
69+
'Referencing Function in Angular expressions is disallowed! Expression: {0}',
70+
fullExpression);
71+
}
72+
}
73+
}
74+
8375
var OPERATORS = {
8476
/* jshint bitwise : false */
8577
'null':function(){return null;},
@@ -699,10 +691,7 @@ Parser.prototype = {
699691
i = indexFn(self, locals),
700692
v;
701693

702-
if (i === "__proto__") {
703-
throw $parseMinErr('isecproto', 'Using __proto__ in Angular expressions is disallowed! '
704-
+'Expression: {0}', parser.text);
705-
}
694+
ensureSafeMemberName(i, parser.text);
706695
if (!o) return undefined;
707696
v = ensureSafeObject(o[i], parser.text);
708697
return v;
@@ -737,7 +726,7 @@ Parser.prototype = {
737726
var fnPtr = fn(scope, locals, context) || noop;
738727

739728
ensureSafeObject(context, parser.text);
740-
ensureSafeObject(fnPtr, parser.text);
729+
ensureSafeFunction(fnPtr, parser.text);
741730

742731
// IE stupidity! (IE doesn't have apply for some native functions)
743732
var v = fnPtr.apply
@@ -832,6 +821,8 @@ function setter(obj, path, setValue, fullExp) {
832821
obj = propertyObj;
833822
}
834823
key = ensureSafeMemberName(element.shift(), fullExp);
824+
ensureSafeObject(obj, fullExp);
825+
ensureSafeObject(obj[key], fullExp);
835826
obj[key] = setValue;
836827
return setValue;
837828
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy