1111 * external/cwe/cwe-116
1212 */
1313
14- // TODO: Proper customizations module, Source class Sink class etc. and qldoc.
1514import javascript
15+ import semmle.javascript.security.dataflow.ImproperCodeSanitization:: ImproperCodeSanitization
1616import DataFlow:: PathGraph
1717private import semmle.javascript.heuristics.HeuristicSinks
1818private import semmle.javascript.security.dataflow.CodeInjectionCustomizations
1919
2020/**
21- * A taint-tracking configuration for reasoning about improper code sanitization vulnerabilities .
21+ * Gets a type-tracked instance of `RemoteFlowSource` using type-tracker `t` .
2222 */
23- class Configuration extends TaintTracking:: Configuration {
24- Configuration ( ) { this = "ImproperCodeSanitization" }
25-
26- override predicate isSource ( DataFlow:: Node source ) { source = source ( ) }
27-
28- override predicate isSink ( DataFlow:: Node sink ) { sink = sink ( ) }
29-
30- override predicate isSanitizer ( DataFlow:: Node sanitizer ) {
31- sanitizer instanceof StringReplaceCall // any string-replace that happens after the bad-sanitizer, is assumed to be a good sanitizer.
32- // TODO: Specialize? This regexp sanitizes: /[<>\b\f\n\r\t\0\u2028\u2029]/g
33- }
34- }
35-
36- private DataFlow:: CallNode source ( ) {
37- result instanceof HtmlSanitizerCall
38- or
39- result = DataFlow:: globalVarRef ( "JSON" ) .getAMemberCall ( "stringify" )
40- }
41-
42- private StringOps:: ConcatenationLeaf sink ( ) {
43- exists ( StringOps:: ConcatenationRoot root , int i |
44- root .getOperand ( i ) = result and
45- not exists ( result .getStringValue ( ) )
46- |
47- exists ( StringOps:: ConcatenationLeaf functionLeaf |
48- functionLeaf = root .getOperand ( any ( int j | j < i ) )
49- |
50- functionLeaf
51- .getStringValue ( )
52- .regexpMatch ( [ ".*function( )?([a-zA-Z0-9]+)?( )?\\(.*" , ".*eval\\(.*" ,
53- ".*new Function\\(.*" , "(^|.*[^a-zA-Z0-9])\\(.*\\)( )?=>.*" ] )
54- )
55- )
56- }
57-
58- DataFlow:: SourceNode remoteFlow ( DataFlow:: TypeTracker t ) {
23+ private DataFlow:: SourceNode remoteFlow ( DataFlow:: TypeTracker t ) {
5924 t .start ( ) and
6025 result instanceof RemoteFlowSource
6126 or
6227 exists ( DataFlow:: TypeTracker t2 | result = remoteFlow ( t2 ) .track ( t2 , t ) )
6328}
6429
65- DataFlow:: SourceNode remoteFlow ( ) { result = remoteFlow ( DataFlow:: TypeTracker:: end ( ) ) }
30+ /**
31+ * Gets a type-tracked reference to a `RemoteFlowSource`.
32+ */
33+ private DataFlow:: SourceNode remoteFlow ( ) { result = remoteFlow ( DataFlow:: TypeTracker:: end ( ) ) }
6634
35+ /**
36+ * Gets a type-back-tracked instance of a code-injection sink using type-tracker `t`.
37+ */
6738private DataFlow:: Node endsInCodeInjectionSink ( DataFlow:: TypeBackTracker t ) {
6839 t .start ( ) and
6940 (
@@ -76,9 +47,11 @@ private DataFlow::Node endsInCodeInjectionSink(DataFlow::TypeBackTracker t) {
7647 exists ( DataFlow:: TypeBackTracker t2 | t = t2 .smallstep ( result , endsInCodeInjectionSink ( t2 ) ) )
7748}
7849
79- DataFlow:: Node endsInCodeInjectionSink ( ) {
80- result = endsInCodeInjectionSink ( DataFlow:: TypeBackTracker:: end ( ) ) and
81- result .getFile ( ) .getBaseName ( ) = "bad-code-sanitization.js" // TODO: TMp
50+ /**
51+ * Gets a reference to to a data-flow node that ends in a code-injection sink.
52+ */
53+ private DataFlow:: Node endsInCodeInjectionSink ( ) {
54+ result = endsInCodeInjectionSink ( DataFlow:: TypeBackTracker:: end ( ) )
8255}
8356
8457from Configuration cfg , DataFlow:: PathNode source , DataFlow:: PathNode sink
0 commit comments