Skip to content
This repository was archived by the owner on Dec 4, 2021. It is now read-only.

Commit c6d87f8

Browse files
Caleb HooverCaleb Hoover
Caleb Hoover
authored and
Caleb Hoover
committed
changes
1 parent 9228fc7 commit c6d87f8

File tree

4 files changed

+82
-41
lines changed

4 files changed

+82
-41
lines changed

bin/check

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ var reports = [];
5656

5757
if (argv.j) {
5858
scope.log = function(type, node, name, value) {
59+
if (typeof value !== 'string')
60+
return;
5961
switch(type) {
6062
case 'SOURCE':
6163
this.reports.push({
@@ -65,37 +67,39 @@ if (argv.j) {
6567
}
6668
});
6769
break;
70+
case 'SCE':
6871
case 'SCES':
69-
source = _.filter(this.reports, function(i) {return i.source.name == value;})[0];
72+
source = _.find(this.reports, function(i) {return value.indexOf(i.source.name) === 0;});
7073
if (source) {
7174
if (!source.chain)
7275
source.chain = [];
7376
source.chain.push({
7477
name: name,
7578
value: value,
7679
line: this.file + ':' + check.pos(node)
77-
})
80+
});
7881
}
79-
// else
80-
// console.log(93, check.pos(node), name, value);
8182
break;
8283
case 'SINK':
83-
source = _.filter(this.reports, function(i) {return i.source.name == value;})[0];
84+
source = _.find(this.reports, function(i) {return value.indexOf(i.source.name) === 0;});
8485
if (source)
8586
source.sink = {
8687
name: name,
8788
line: this.file + ':' + check.pos(node)
8889
};
89-
// else
90-
// console.log(93, check.pos(node), name, value);
90+
91+
if (this.reports.indexOf(source) != -1) {
92+
this.reports.splice(this.reports.indexOf(source), 1);
93+
reports.push(source);
94+
}
9195
break;
9296
}
9397
};
9498

9599
scope.leaveScope = function() {
96100
var r = _.filter(this.reports, function(i) {return !!i.sink;});
97101
// if (r.length !== 0)
98-
// console.log(r);
102+
// console.log(r);
99103
reports = reports.concat(r);
100104
};
101105
}

check.js

Lines changed: 66 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function(scope, node, ce) { // http.get
4848
var func = ce.arguments[1];
4949

5050
func.scope.sources.push(func.params[1]);
51-
func.scope.log('SOURCE', node, '', func.params[1]);
51+
func.scope.log('SOURCE', node, false, func.params[1]);
5252
traverse(func.body, func.scope);
5353
return true;
5454
}, function(scope, node, ce) {// (new require('hapi').server()).route()
@@ -68,7 +68,7 @@ function(scope, node, ce) { // http.get
6868

6969
if (func && func.scope) {
7070
func.scope.sources.push(func.params[0]);
71-
func.scope.log('SOURCE', node, '', func.params[0]);
71+
func.scope.log('SOURCE', node, false, func.params[0]);
7272
traverse(func.body, func.scope);
7373

7474
}
@@ -88,7 +88,7 @@ function(scope, node, ce) { // http.get
8888

8989
if (func && func.scope) {
9090
func.scope.sources.push(func.params[0]);
91-
func.scope.log('SOURCE', node, '', func.params[0]);
91+
func.scope.log('SOURCE', node, false, func.params[0]);
9292
traverse(func.body, func.scope);
9393

9494
}
@@ -105,7 +105,7 @@ function(scope, node, ce) { // http.get
105105
var func = ce.arguments[2]; // the callback
106106
if (func) {
107107
func.scope.sources.push(func.params[1]); // data
108-
func.scope.log('SOURCE', node, '', func.params[1]);
108+
func.scope.log('SOURCE', node, false, func.params[1]);
109109
traverse(func.body, func.scope);
110110
}
111111
return true;
@@ -142,7 +142,13 @@ function(scope, node, ce) { // http.get
142142
if (ast) {
143143
if (flags.verbose)
144144
console.log(' ---- '.yellow, pkg);
145-
var newScope = new Scope({sinks: sinks, sources: sources, file:pkg, log:scope.log, leaveScope:scope.leaveScope});
145+
var newScope = new Scope({
146+
sinks: sinks,
147+
sources: sources,
148+
file: pkg,
149+
log: scope.log,
150+
leaveScope: scope.leaveScope
151+
});
146152
traverse(ast, newScope);
147153
// scope.log('EXPORTS', ast, newScope.vars.module.exports);
148154

@@ -169,8 +175,8 @@ Scope = module.exports.Scope = function(scope) {
169175
this.file = scope.file;
170176
if (!baseFile) baseFile = scope.file;
171177
this.log = scope.log || log;
172-
this.createNewScope = scope.createNewScope;
173178
this.leaveScope = scope.leaveScope;
179+
this.createNewScope = scope.createNewScope;
174180
this.reports = [];
175181
};
176182

@@ -251,38 +257,38 @@ Scope.prototype.resolveStatement = function(node) {
251257
}
252258

253259
var ceName = scope.resolve(ce.name);
254-
260+
255261
var t = 'CES';
256262

257263
if (ce.arguments)
258264
ce.arguments.some(function (arg) {
259-
if (!arg)
265+
if (!arg || (arg.scope && arg.params && arg.body))
260266
return false;
261267
var resolved = scope.resolve(arg);
262268
var source = resolved;
263-
269+
264270
if (scope.isSource(arg.name || arg) || scope.isSource(resolved.name || resolved) ||
265-
(arg.left?_.some(climbBE(arg), function (a) {
271+
(traverseJSON(arg, function (a) {
266272
if (!a) return false;
267273
var r = scope.resolve(a);
268274
if (scope.isSource(a.name || a) || scope.isSource(r.name || r)) {
269275
source = r;
270276
return true;
271277
}
272278
return false;
273-
}):false)) {
279+
}))) {
274280

275281
// If the function is a sink and there is a source, return as sink;
276282
// If not a sink but still has source, return as a Source CES (possible taint)
277283
t = (scope.isSink(ce.name) || scope.isSink(ceName))?'SINK':'SCES';
278-
scope.log(t, node, ce.name, source);
284+
scope.log(t, node, ce.name, source.name || source);
279285
return true;
280286
}
281287
return false;
282288
});
283289

284-
if ((flags.verbose || t[0] == 'S') && typeof ceName == 'string')
285-
this.log(t, node, ce.raw, typeof ceName == 'string'?ceName:{});
290+
if (flags.verbose && typeof ceName == 'string')
291+
this.log(t, node, ce.name, typeof ceName == 'string'?ceName:{});
286292

287293
return ce;
288294
case 'AssignmentExpression':
@@ -384,6 +390,7 @@ Scope.prototype.resolveExpression = function(right, isSourceCB) {
384390
if (flags.verbose)
385391
this.log('ARRAY', right, array);
386392
return array;
393+
case 'LogicalExpression':
387394
case 'BinaryExpression': // A + B - C * D
388395
var bin = {
389396
left: this.resolveExpression(right.left, isSourceCB),
@@ -405,29 +412,27 @@ Scope.prototype.resolveExpression = function(right, isSourceCB) {
405412
if (ceName && typeof ceName == 'string') {
406413
if (ce.arguments) {
407414
ce.arguments.some(function (arg) {
408-
if (!arg)
409-
return false;
415+
if (!arg || (arg.scope && arg.params && arg.body))
416+
return false;
410417
var resolved = scope.resolve(arg);
411418
var source = resolved;
412419

413420
if (scope.isSource(arg.name || arg) || scope.isSource(resolved.name || resolved) ||
414-
arg.left?_.some(climbBE(arg), function (a) {
421+
(traverseJSON(arg, function (a) {
415422
if (!a) return false;
416423
var r = scope.resolve(a);
417424
if (scope.isSource(a.name || a) || scope.isSource(r.name || r)) {
418425
source = r;
419426
return true;
420427
}
421428
return false;
422-
}):false) {
429+
}))) {
423430

424-
if (scope.isSource(ce.name) || scope.isSink(ceName)) {
425-
scope.log('SINK', right, ce.name, source);
426-
return true;
427-
} else {
428-
t = 'SCE';
429-
return false;
430-
}
431+
432+
// If the function is a sink and there is a source, return as sink;
433+
// If not a sink but still has source, return as a Source CES (possible taint)
434+
t = (scope.isSink(ce.name) || scope.isSink(ceName))?'SINK':'SCES';
435+
scope.log(t, right, ce.name, source);
431436
}
432437
return false;
433438
});
@@ -452,7 +457,9 @@ Scope.prototype.resolveExpression = function(right, isSourceCB) {
452457
case 'FunctionExpression': // functions
453458
var fe = scope.resolveFunctionExpression(right);
454459
return fe;
455-
460+
default:
461+
// console.log(right.type, pos(right));
462+
return {};
456463
}
457464
};
458465

@@ -597,7 +604,8 @@ Scope.prototype.traverse = function(ast, returnCB) {
597604
// (scope.leaveScope || function () {
598605
// console.log('leaving scope'.yellow);
599606
// })();
600-
scope.leaveScope();
607+
if (scope.leaveScope)
608+
scope.leaveScope();
601609
};
602610

603611
Scope.prototype.resolvePath = function(file, cb) {
@@ -611,7 +619,8 @@ Scope.prototype.resolvePath = function(file, cb) {
611619
try {
612620
pkg = resolve.sync(file, {basedir: String(this.file).split('/').slice(0,-1).join('/')});
613621
} catch (e) {
614-
console.error(String(e));
622+
if (flags.verbose)
623+
console.error(String(e));
615624
return false;
616625
}
617626

@@ -662,7 +671,6 @@ traverse = module.exports.traverse = function(ast, scope) {
662671
scope.log('SOURCES', ast, scope.sources);
663672
}
664673

665-
666674
ast.body.forEach(function (node) {
667675
if (node.type == 'ExpressionStatement')
668676
node = node.expression;
@@ -674,7 +682,8 @@ traverse = module.exports.traverse = function(ast, scope) {
674682
// console.log('leaving scope'.yellow);
675683
// })();
676684
// }
677-
scope.leaveScope();
685+
if (scope.leaveScope)
686+
scope.leaveScope();
678687
};
679688

680689
astFromFile = module.exports.astFromFile = function(file, output) {
@@ -710,4 +719,30 @@ climbBE = module.exports.climbBE = function (be, func) {
710719
// Convience function to return the line of a node assuming a node has one.
711720
module.exports.pos = pos = function(node) {
712721
return node.loc ? String(node.loc.start.line) : "-1";
713-
};
722+
};
723+
724+
// function traverseJSON(o,func) {
725+
// for (var i in o) {
726+
// func(o[i]);
727+
// if (o[i] !== null && typeof(o[i])=="object") {
728+
// //going on step down in the object tree!!
729+
// traverseJSON(o[i],func);
730+
// }
731+
// }
732+
// }
733+
734+
function traverseJSON(o,func) {
735+
return typeof o == 'object'? _.some(o, function(i) {
736+
if (!i)
737+
return false;
738+
if (typeof i == 'object') {
739+
if (!i || (i.scope && i.params && i.body))
740+
return false;
741+
return traverseJSON(i, func);
742+
} else {
743+
return func(i);
744+
}
745+
746+
return false;
747+
}) : false;
748+
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"esprima": "~1.2.2",
1313
"underscore": "~1.7.0",
1414
"resolve": "*",
15-
"yargs": "~1.3.3"
15+
"yargs": "~1.3.3",
16+
"estraverse": "~1.9.1"
1617
},
1718
"devDependencies": {},
1819
"repository": {

tests/fs.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
var fs = require('fs');
12
var file = process.argv[2]; // Source
2-
require('fs').writeFileSync(file, 'BAD STUFF'); // Sink
3+
fs.writeFileSync(file, 'BAD STUFF'); // Sink

0 commit comments

Comments
 (0)