Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b1c0296

Browse files
author
Max Schaefer
committed
JavaScript: Add support for annotation comments specifying additional sources and sinks.
1 parent 3575078 commit b1c0296

7 files changed

Lines changed: 101 additions & 1 deletion

File tree

javascript/ql/src/Security/Summaries/ExtractSinkSummaries.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import AllConfigurations
1111
import PortalExitSource
12+
import SinkFromAnnotation
1213

1314
from TaintTracking::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink,
1415
Portal p

javascript/ql/src/Security/Summaries/ExtractSourceSummaries.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import AllConfigurations
1111
import PortalEntrySink
12+
import SourceFromAnnotation
1213

1314
from TaintTracking::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink,
1415
Portal p

javascript/ql/src/Security/Summaries/Shared.qll

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,59 @@ predicate sinkFlowLabelSpec(DataFlow::FlowLabel lbl, string spec) {
3535
spec = "" and
3636
lbl instanceof DataFlow::StandardFlowLabel
3737
}
38+
39+
/**
40+
* A comment that annotates data flow nodes as sources/sinks.
41+
*
42+
* Such a comment starts with "Semmle:", possibly preceded by whitespace, and
43+
* may contain specifications of the form "source: label,config" and "sink: label, config"
44+
* where again whitespace is not significant and the ",config" part may be missing.
45+
*
46+
* It applies to any data flow node that ends on the line where the comment starts,
47+
* and annotates the node as being a source/sink with the given flow label(s) for
48+
* the given configuration (or any configuration if omitted).
49+
*/
50+
class AnnotationComment extends Comment {
51+
string ann;
52+
53+
AnnotationComment() {
54+
ann = getText().regexpCapture("(?s)\\s*Semmle:(.*)", 1)
55+
}
56+
57+
/**
58+
* Holds if this comment applies to `nd`, that is, it starts on the same line on
59+
* which `nd` ends.
60+
*/
61+
predicate appliesTo(DataFlow::Node nd) {
62+
exists (string file, int line |
63+
getLocation().hasLocationInfo(file, line, _, _, _) and
64+
nd.hasLocationInfo(file, _, _, line, _)
65+
)
66+
}
67+
68+
/**
69+
* Holds if this comment contains an annotation of the form `source: label, config`
70+
* or `source: label` (modulo whitespace). In the latter case, `config` may be
71+
* any configuration.
72+
*/
73+
predicate specifiesSource(DataFlow::FlowLabel label, DataFlow::Configuration config) {
74+
exists (string spec |
75+
spec = ann.regexpFind("(?<=\\bsource:)\\s*[^\\s,]+(\\s*,\\s*[^\\s,])?", _, _) and
76+
sourceFlowLabelSpec(label, spec.splitAt(",", 0).trim()) and
77+
configSpec(config, spec.splitAt(",", 1).trim())
78+
)
79+
}
80+
81+
/**
82+
* Holds if this comment contains an annotation of the form `sink: label, config`
83+
* or `sink: label` (modulo whitespace). In the latter case, `config` may be
84+
* any configuration.
85+
*/
86+
predicate specifiesSink(string label, string config) {
87+
exists (string spec |
88+
spec = ann.regexpFind("(?<=\\bsink:)\\s*[^\\s,]+(\\s*,\\s*[^\\s,]+)?", _, _) and
89+
sinkFlowLabelSpec(label, spec.splitAt(",", 0).trim()) and
90+
configSpec(config, spec.splitAt(",", 1).trim())
91+
)
92+
}
93+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import javascript
2+
import Shared
3+
4+
/**
5+
* A data flow node that is annotated as a sink.
6+
*/
7+
class SinkFromAnnotation extends DataFlow::AdditionalSink {
8+
AnnotationComment c;
9+
10+
SinkFromAnnotation() {
11+
c.appliesTo(this) and
12+
c.specifiesSink(_, _)
13+
}
14+
15+
override predicate isSinkFor(DataFlow::Configuration cfg, DataFlow::FlowLabel lbl) {
16+
c.specifiesSink(lbl, cfg)
17+
}
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import javascript
2+
import Shared
3+
4+
/**
5+
* A data flow node that is annotated as a source.
6+
*/
7+
class SourceFromAnnotation extends DataFlow::AdditionalSource {
8+
AnnotationComment c;
9+
10+
SourceFromAnnotation() {
11+
c.appliesTo(this) and
12+
c.specifiesSource(_, _)
13+
}
14+
15+
override predicate isSourceFor(DataFlow::Configuration cfg, DataFlow::FlowLabel lbl) {
16+
c.specifiesSource(lbl, cfg)
17+
}
18+
}

javascript/ql/test/query-tests/Security/Summaries/ExtractSinkSummaries.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
| (parameter (member (root https://www.npmjs.com/package/infer-sources) hashPass) 0) | data | InsufficientPasswordHash |
99
| (parameter (member (root https://www.npmjs.com/package/infer-sources) hashPass) 0) | taint | CodeInjection |
1010
| (parameter (member (root https://www.npmjs.com/package/infer-sources) hashPass) 0) | taint | InsufficientPasswordHash |
11+
| (parameter (member (root https://www.npmjs.com/package/infer-sources) mkdirp) 0) | taint | TaintedPath |
1112
| (parameter (member (root https://www.npmjs.com/package/infer-sources) multiple) 0) | data | CodeInjection |
1213
| (parameter (member (root https://www.npmjs.com/package/infer-sources) multiple) 0) | data | CommandInjection |
1314
| (parameter (member (root https://www.npmjs.com/package/infer-sources) multiple) 0) | taint | CodeInjection |

javascript/ql/test/query-tests/Security/Summaries/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,10 @@ function h(y) {
161161
return y;
162162
}
163163

164+
function mkdirp(path) {
165+
path /* Semmle: sink: taint, TaintedPath */
166+
}
167+
164168
module.exports = {
165169
codeInjection: codeInjection,
166170
commandInjection: commandInjection,
@@ -183,5 +187,6 @@ module.exports = {
183187
notACookieSource: notACookieSource,
184188
invoke: invoke,
185189
g: g,
186-
h: h
190+
h: h,
191+
mkdirp: mkdirp
187192
}

0 commit comments

Comments
 (0)