4
4
CE - Call Expression (functions)
5
5
SCE - (source) Call Expression
6
6
SCES - (source) Call Expression Statement
7
- SASSIGN - Assign as a sink
7
+ SINK - Assign as a sink
8
8
*/
9
9
10
10
var fs = require ( 'fs' ) ,
@@ -118,7 +118,7 @@ var returnCB = function (fe, node) {
118
118
var arg = scope . resolveExpression ( node . argument ) ;
119
119
Scope . log = l ;
120
120
121
- var source = scope . resolveSource ( arg ) ;
121
+ var source = scope . resolveTree ( scope . isSource , arg ) ;
122
122
if ( source ) {
123
123
scope . source [ fe . name ] = fe . name ;
124
124
Scope . log . call ( this , 'RETURN' , node , fe . names )
@@ -133,39 +133,54 @@ function Scope (scope) {
133
133
if ( ! this . vars . module ) this . vars . module = { exports : { } } ;
134
134
if ( ! this . vars . exports ) this . vars . exports = { } ;
135
135
if ( ! this . vars . global ) this . vars . global = { } ;
136
+
136
137
// dynamic list of sources and sinks as variables get set to them
137
138
this . sources = scope . sources || JSON . parse ( JSON . stringify ( Sources ) ) ; // clever clone
138
139
this . sinks = scope . sinks || Sinks . slice ( 0 ) ; // another clever clone but for arrays
140
+
139
141
this . file = scope . file ;
140
142
141
143
if ( ! Scope . baseFile )
142
144
Scope . baseFile = scope . file ;
143
145
144
- this . reports = scope . reports || [ { source : { name : 'process.argv' , line : path . relative ( Scope . baseFile . split ( '/' ) . reverse ( ) . slice ( 1 ) . reverse ( ) . join ( '/' ) , this . file ) } } ] ;
146
+ file = path . relative ( Scope . baseFile . split ( '/' ) . reverse ( ) . slice ( 1 ) . reverse ( ) . join ( '/' ) , this . file ) ;
147
+ this . reports = scope . reports || [ { source : { name : 'process.argv' , line : file + ':0' } } ] ;
145
148
}
146
149
147
150
Scope . log = function ( type , node , name , value ) { } ;
148
151
149
152
// handles creation of variables.
150
153
Scope . prototype . track = function ( variable ) {
154
+ debugger ;
151
155
var scope = this ;
152
156
var name = variable . id . name ;
153
157
158
+ var type = "VAR" ;
154
159
var expr = this . resolveExpression ( variable . init , function ( value ) {
155
- if ( value ) {
156
-
157
- var source = scope . resolveSource ( value ) ;
158
- if ( source ) {
159
- scope . sources [ name ] = source ;
160
- Scope . log . call ( scope , 'SOURCE' , variable , name , source ) ;
161
- }
160
+ if ( ! value ) {
161
+ console . log ( 'value was undefined for some reason' ) ;
162
+ throw new Exception ( 'value was undefined' ) ;
162
163
}
163
164
165
+ var danger ;
166
+ if ( variable . type == 'Identifier' ) {
167
+ danger = scope . resolveTree ( scope . isSink , value ) ;
168
+ if ( danger ) {
169
+ scope . sinks . push ( name ) ;
170
+ type = 'SINK' ;
171
+ }
172
+ } else {
173
+ danger = scope . resolveTree ( scope . isSource , value ) ;
174
+ if ( danger ) {
175
+ scope . sources [ name ] = scope . resolve ( name ) ;
176
+ type = 'SOURCE' ;
177
+ }
178
+ }
164
179
} ) ;
165
180
166
181
this . vars [ name ] = expr ;
167
182
168
- Scope . log . call ( this , 'VAR' , variable , name , expr ? ( expr . raw || expr . name || expr ) : undefined ) ;
183
+ Scope . log . call ( this , type , variable , name , expr ? ( expr . raw || expr . name || expr ) : undefined ) ;
169
184
} ;
170
185
171
186
@@ -226,7 +241,7 @@ Scope.prototype.resolveStatement = function(node) {
226
241
if ( arg . params && arg . body && arg . scope )
227
242
return false ; // skips callbacks
228
243
229
- var source = scope . resolveSource ( arg ) ;
244
+ var source = scope . resolveTree ( scope . isSource , arg ) ;
230
245
if ( source ) {
231
246
232
247
// If the function is a sink and there is a source, return as sink;
@@ -246,41 +261,46 @@ Scope.prototype.resolveStatement = function(node) {
246
261
case 'AssignmentExpression' :
247
262
var assign = scope . resolveAssignment ( node ) ;
248
263
var names = assign . names ;
264
+ var type = 'ASSIGN' ;
249
265
var value = this . resolveExpression ( assign . value , function ( value , isSource ) {
250
- if ( value ) {
251
- var resolved = scope . resolve ( value ) ;
252
- var source ;
253
- if ( resolved && typeof resolved == 'string' ) {
254
- if ( node . right . type == 'Identifier' &&
255
- ( scope . isSink ( value . name || value ) || scope . isSink ( resolved . name || resolved ) ) ) {
256
- scope . sinks . push ( names ) ;
257
- Scope . log . call ( scope , 'SASSIGN' , node , names . length == 1 ?names [ 0 ] :names , value ) ;
258
- } else {
259
- var source = scope . resolveSource ( value ) ;
260
- if ( source ) {
261
- scope . sources [ names ] = source ;
262
- Scope . log . call ( scope , 'SOURCE' , node , names . length == 1 ?names [ 0 ] :names , source ) ;
263
- }
264
- }
266
+ if ( ! value ) {
267
+ console . log ( 'value was undefined for some reason' ) ;
268
+ throw new Exception ( 'value was undefined' ) ;
269
+ }
270
+ debugger ;
271
+
272
+ var danger ;
273
+ if ( assign . value . type == 'Identifier' ) {
274
+ danger = scope . resolveTree ( scope . isSink , value ) ;
275
+ if ( danger ) {
276
+ names . forEach ( function ( name ) {
277
+ scope . sinks . push ( name ) ;
278
+ } ) ;
279
+ type = 'SINK'
280
+ }
281
+ } else {
282
+ debugger ;
283
+ danger = scope . resolveTree ( scope . isSource , value ) ;
284
+ if ( danger ) {
285
+ names . forEach ( function ( name ) {
286
+ scope . sources [ name ] = scope . resolve ( value ) ;
287
+ } ) ;
288
+ type = 'SOURCE' ;
265
289
}
266
290
}
267
291
} ) ;
268
292
269
293
names . forEach ( function ( name ) {
270
294
try {
271
295
if ( node . left . type == 'MemberExpression' ) {
272
- eval ( 'scope.vars.' + name + ' = ' + JSON . stringify ( value ) ) ;
296
+ v = typeof value == "object" ? JSON . stringify ( value ) : String ( value ) ;
297
+ eval ( 'scope.vars.' + name + ' = "' + v + '"' ) ;
273
298
}
274
- } catch ( e ) {
275
- // if (flags.debug) {
276
- // console.error('Error reading line:'.red, scope.file + ':' + pos(node));
277
- // console.error(e.stack);
278
- // }
279
- }
299
+ } catch ( e ) { }
280
300
} ) ;
281
301
282
302
if ( value )
283
- Scope . log . call ( this , 'ASSIGN' , node , names . length == 1 ?names [ 0 ] :names , util . inspect ( value . raw || value , { depth : 1 } ) ) ;
303
+ Scope . log . call ( this , type , node , names . length == 1 ?names [ 0 ] :names , util . inspect ( value . raw || value , { depth : 1 } ) ) ;
284
304
break ;
285
305
case 'FunctionDeclaration' :
286
306
if ( Scope . createNewScope )
@@ -343,7 +363,9 @@ Scope.prototype.resolveExpression = function(right, isSourceCB) {
343
363
var scope = this ;
344
364
switch ( right . type ) {
345
365
case 'Literal' : // string, number, etc..
346
- return "'" + eval ( right . raw ) + "'" ;
366
+ return typeof right . value == 'string' ?
367
+ "'" + right . value + "'" : right . value ;
368
+ // return "'" + eval(right.raw) + "'";
347
369
case 'Identifier' : // variables, etc...
348
370
// if variable is being set to a bad variable, mark it too as bad
349
371
if ( isSourceCB ) {
@@ -385,8 +407,8 @@ Scope.prototype.resolveExpression = function(right, isSourceCB) {
385
407
ce . arguments . some ( function ( arg ) {
386
408
if ( arg . params && arg . body && arg . scope )
387
409
return false ; // skips callbacks
388
- var source = scope . resolveSource ( arg ) ;
389
- if ( source ) { // I do want to set source to resolveSource( arg)
410
+ var source = scope . resolveTree ( scope . isSource , arg ) ;
411
+ if ( source ) { // I do want to set source to resolveTree(scope.isSource, arg)
390
412
// If the function is a sink and there is a source, return as sink;
391
413
// If not a sink but still has source, return as a Source CES (possible taint)
392
414
@@ -425,39 +447,46 @@ Scope.prototype.resolveExpression = function(right, isSourceCB) {
425
447
case 'AssignmentExpression' : // a = b
426
448
var assign = scope . resolveAssignment ( right ) ;
427
449
var names = assign . names ;
450
+ var type = 'ASSIGN' ;
428
451
var value = this . resolveExpression ( assign . value , function ( value , isSource ) {
429
- if ( value ) {
430
- var resolved = scope . resolve ( value ) ;
431
- if ( resolved && typeof resolved == 'string' ) {
432
- if ( scope . isSink ( value . name || value ) || scope . isSink ( resolved . name || resolved ) ) {
433
- scope . sinks . push ( names ) ;
434
- Scope . log . call ( scope , 'SASSIGN' , right , names . length == 1 ?names [ 0 ] :names , value ) ;
435
- } else {
436
- var source = scope . resolveSource ( value ) ;
437
- if ( source ) {
438
- scope . sources [ names ] = source ;
439
- Scope . log . call ( scope , 'SOURCE' , right , names . length == 1 ?names [ 0 ] :names , source ) ;
440
- }
441
- }
452
+ if ( ! value ) {
453
+ console . log ( 'value was undefined for some reason' ) ;
454
+ throw new Exception ( 'value was undefined' ) ;
455
+ }
456
+
457
+ var danger ;
458
+ if ( assign . value . type == 'Identifier' ) {
459
+ danger = scope . resolveTree ( scope . isSink , value ) ;
460
+ if ( danger ) {
461
+ names . forEach ( function ( name ) {
462
+ scope . sinks . push ( name ) ;
463
+ } ) ;
464
+ type = 'SINK'
465
+ }
466
+ } else {
467
+ danger = scope . resolveTree ( scope . isSource , value ) ;
468
+ if ( danger ) {
469
+ names . forEach ( function ( name ) {
470
+ scope . sources . push ( name ) ;
471
+ } ) ;
472
+ type = 'SOURCE' ;
442
473
}
443
474
}
444
475
} ) ;
445
476
446
477
names . forEach ( function ( name ) {
447
478
try {
448
- if ( right . left . type == 'MemberExpression' ) {
449
- if ( scope . vars [ name ] || scope . vars [ name . split ( '.' ) . slice ( - 1 ) . join ( '.' ) ] )
450
- eval ( 'scope.vars.' + name + ' = ' + JSON . stringify ( value ) ) ;
451
- else
452
- eval ( 'scope.vars.' + name + ' = ' + JSON . stringify ( value ) ) ;
479
+ if ( node . left . type == 'MemberExpression' ) {
480
+ v = typeof value == "object" ? JSON . stringify ( value ) : String ( value ) ;
481
+ eval ( 'scope.vars.' + name + ' = "' + v + '"' ) ;
453
482
}
454
483
} catch ( e ) {
455
484
456
485
}
457
486
} ) ;
458
487
459
488
if ( value )
460
- Scope . log . call ( this , 'ASSIGN' , right , names . length == 1 ?names [ 0 ] :names , util . inspect ( value . raw || value , { depth : 1 } ) ) ;
489
+ Scope . log . call ( this , type , right , names . length == 1 ?names [ 0 ] :names , util . inspect ( value . raw || value , { depth : 1 } ) ) ;
461
490
462
491
return value ;
463
492
}
@@ -570,7 +599,7 @@ Scope.prototype.resolveFunctionExpression = function(node, newScope) {
570
599
Scope . log = l ;
571
600
572
601
if ( fe . name ) {
573
- var source = scope . resolveSource ( arg ) ;
602
+ var source = scope . resolveTree ( scope . isSource , arg ) ;
574
603
if ( source ) {
575
604
576
605
scope . sources [ fe . name ] = source ;
@@ -584,33 +613,33 @@ Scope.prototype.resolveFunctionExpression = function(node, newScope) {
584
613
585
614
// complicated code to check if the argument is a source
586
615
// and returns the part of it that is the source
587
- Scope . prototype . resolveSource = function ( expr ) {
616
+ Scope . prototype . resolveTree = function ( func , expr ) {
588
617
var scope = this ;
589
618
590
619
// specifically handles call expressions
591
620
if ( expr . name && expr . arguments && expr . raw ) {
592
- var source = false ;
621
+ var danger = false ;
593
622
expr . arguments . some ( function ( i ) {
594
- source = scope . resolveSource ( i ) ;
595
- return ! ! source ;
623
+ danger = scope . resolveTree ( func , i ) ;
624
+ return ! ! danger ;
596
625
} ) ;
597
- return source ;
626
+ return danger ;
598
627
} else if ( expr . body && expr . params && expr . scope ) {
599
628
return false ;
600
629
}
601
630
602
631
var resolved = this . resolve ( expr ) ;
603
632
604
633
if ( typeof expr == 'object' || typeof resolved == 'object' ) {
605
- var source ;
634
+ var danger ;
606
635
( traverseJSON ( expr , function ( a ) {
607
636
if ( ! a ) return false ;
608
- source = scope . resolveSource ( a ) ;
609
- return source ;
637
+ danger = scope . resolveTree ( func , a ) ;
638
+ return danger ;
610
639
} ) ) ;
611
- return source ;
640
+ return danger ;
612
641
} else {
613
- if ( scope . isSource ( expr . name || expr ) || scope . isSource ( resolved . name || resolved ) )
642
+ if ( func . call ( scope , expr . name || expr ) || func . call ( scope , resolved . name || resolved ) )
614
643
return resolved ;
615
644
}
616
645
0 commit comments