Skip to content

Commit 9d02e7e

Browse files
committed
Partial address comments - refactor qll lib files and add testcase
1 parent 56378eb commit 9d02e7e

File tree

4 files changed

+122
-164
lines changed

4 files changed

+122
-164
lines changed

javascript/frameworks/cap/lib/advanced_security/javascript/frameworks/cap/CAPPathInjectionQuery.qll

Lines changed: 1 addition & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -5,169 +5,7 @@
55
*/
66

77
import javascript
8-
import advanced_security.javascript.frameworks.cap.CDS
9-
10-
/**
11-
* An access to the `utils` module on a CDS facade.
12-
*/
13-
class CdsUtilsModuleAccess extends API::Node {
14-
CdsUtilsModuleAccess() { exists(CdsFacade cds | this = cds.getMember("utils")) }
15-
}
16-
17-
class PathConverters extends DataFlow::Node {
18-
PathConverters() {
19-
exists(CdsUtilsModuleAccess utils |
20-
utils.getMember(["decodeURI", "decodeURIComponent", "local"]).getACall() = this
21-
)
22-
}
23-
24-
SourceNode pathConvertersUtils(TypeTracker t) {
25-
t.start() and
26-
result = this
27-
or
28-
exists(TypeTracker t2 | result = pathConvertersUtils(t2).track(t2, t))
29-
}
30-
31-
SourceNode pathConvertersUtils() { result = pathConvertersUtils(TypeTracker::end()) }
32-
33-
DataFlow::Node getPath() { pathConvertersUtils().(DataFlow::CallNode).getAnArgument() = result }
34-
}
35-
36-
class PathPredicates extends DataFlow::Node {
37-
PathPredicates() {
38-
exists(CdsUtilsModuleAccess utils | utils.getMember(["isdir", "isfile"]).getACall() = this)
39-
}
40-
41-
SourceNode pathPredicateUtils(TypeTracker t) {
42-
t.start() and
43-
result = this
44-
or
45-
exists(TypeTracker t2 | result = pathPredicateUtils(t2).track(t2, t))
46-
}
47-
48-
SourceNode pathPredicateUtils() { result = pathPredicateUtils(TypeTracker::end()) }
49-
50-
DataFlow::Node getPath() { pathPredicateUtils().(DataFlow::CallNode).getAnArgument() = result }
51-
}
52-
53-
class DirectoryReaders extends DataFlow::Node {
54-
DirectoryReaders() {
55-
exists(CdsUtilsModuleAccess utils |
56-
utils.getMember(["find", "stat", "readdir"]).getACall() = this
57-
)
58-
}
59-
60-
SourceNode directoryReaderUtils(TypeTracker t) {
61-
t.start() and
62-
result = this
63-
or
64-
exists(TypeTracker t2 | result = directoryReaderUtils(t2).track(t2, t))
65-
}
66-
67-
SourceNode directoryReaderUtils() { result = directoryReaderUtils(TypeTracker::end()) }
68-
69-
DataFlow::Node getPath() { directoryReaderUtils().(DataFlow::CallNode).getAnArgument() = result }
70-
}
71-
72-
class DirectoryWriters extends DataFlow::Node {
73-
DirectoryWriters() {
74-
exists(CdsUtilsModuleAccess utils |
75-
utils.getMember(["mkdirp", "rmdir", "rimraf", "rm"]).getACall() = this
76-
)
77-
}
78-
79-
SourceNode directoryWriterUtils(TypeTracker t) {
80-
t.start() and
81-
result = this
82-
or
83-
exists(TypeTracker t2 | result = directoryWriterUtils(t2).track(t2, t))
84-
}
85-
86-
SourceNode directoryWriterUtils() { result = directoryWriterUtils(TypeTracker::end()) }
87-
88-
DataFlow::Node getPath() { directoryWriterUtils().(DataFlow::CallNode).getAnArgument() = result }
89-
}
90-
91-
class FileReaders extends DataFlow::Node {
92-
FileReaders() { exists(CdsUtilsModuleAccess utils | utils.getMember(["read"]).getACall() = this) }
93-
94-
SourceNode fileReaderUtils(TypeTracker t) {
95-
t.start() and
96-
result = this
97-
or
98-
exists(TypeTracker t2 | result = fileReaderUtils(t2).track(t2, t))
99-
}
100-
101-
SourceNode fileReaderUtils() { result = fileReaderUtils(TypeTracker::end()) }
102-
103-
DataFlow::Node getPath() { fileReaderUtils().(DataFlow::CallNode).getArgument(0) = result }
104-
}
105-
106-
class FileWriters extends DataFlow::Node {
107-
FileWriters() {
108-
exists(CdsUtilsModuleAccess utils | utils.getMember(["append", "write"]).getACall() = this)
109-
}
110-
111-
SourceNode fileWriterUtils(TypeTracker t) {
112-
t.start() and
113-
result = this
114-
or
115-
exists(TypeTracker t2 | result = fileWriterUtils(t2).track(t2, t))
116-
}
117-
118-
SourceNode fileWriterUtils() { result = fileWriterUtils(TypeTracker::end()) }
119-
120-
DataFlow::Node getData() {
121-
exists(DataFlow::CallNode write |
122-
write = fileWriterUtils() and
123-
(
124-
write.getNumArgument() = 1 and
125-
write.getArgument(0) = result
126-
or
127-
write.getNumArgument() = 2 and
128-
write.getArgument(1) = result
129-
)
130-
)
131-
}
132-
133-
DataFlow::Node getPath() {
134-
exists(DataFlow::CallNode write |
135-
write = fileWriterUtils() and
136-
(
137-
write.getAMemberCall("to").getAnArgument() = result
138-
or
139-
write.getNumArgument() = 2 and
140-
write.getArgument(0) = result
141-
)
142-
)
143-
}
144-
}
145-
146-
class FileReaderWriters extends DataFlow::Node {
147-
FileReaderWriters() {
148-
exists(CdsUtilsModuleAccess utils | utils.getMember(["copy"]).getACall() = this)
149-
}
150-
151-
SourceNode fileReaderWriterUtils(TypeTracker t) {
152-
t.start() and
153-
result = this
154-
or
155-
exists(TypeTracker t2 | result = fileReaderWriterUtils(t2).track(t2, t))
156-
}
157-
158-
SourceNode fileReaderWriterUtils() { result = fileReaderWriterUtils(TypeTracker::end()) }
159-
160-
DataFlow::Node getPath() {
161-
exists(DataFlow::CallNode copy |
162-
copy = fileReaderWriterUtils() and
163-
(
164-
copy.getAMemberCall("to").getArgument(_) = result
165-
or
166-
copy.getArgument(_) = result
167-
)
168-
)
169-
}
170-
}
8+
import advanced_security.javascript.frameworks.cap.CDSUtils
1719

17210
abstract class UtilsSink extends DataFlow::Node { }
17311

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import javascript
2+
import advanced_security.javascript.frameworks.cap.CDS
3+
4+
/**
5+
* An access to the `utils` module on a CDS facade.
6+
*/
7+
class CdsUtilsModuleAccess extends API::Node {
8+
CdsUtilsModuleAccess() { exists(CdsFacade cds | this = cds.getMember("utils")) }
9+
}
10+
11+
class PathConverters extends DataFlow::CallNode {
12+
PathConverters() {
13+
exists(CdsUtilsModuleAccess utils |
14+
utils.getMember(["decodeURI", "decodeURIComponent", "local"]).getACall() = this
15+
)
16+
}
17+
18+
DataFlow::Node getPath() { this.getAnArgument() = result }
19+
}
20+
21+
class PathPredicates extends DataFlow::CallNode {
22+
PathPredicates() {
23+
exists(CdsUtilsModuleAccess utils | utils.getMember(["isdir", "isfile"]).getACall() = this)
24+
}
25+
26+
DataFlow::Node getPath() { this.getAnArgument() = result }
27+
}
28+
29+
class DirectoryReaders extends DataFlow::CallNode {
30+
DirectoryReaders() {
31+
exists(CdsUtilsModuleAccess utils |
32+
utils.getMember(["find", "stat", "readdir"]).getACall() = this
33+
)
34+
}
35+
36+
DataFlow::Node getPath() { this.getAnArgument() = result }
37+
}
38+
39+
class DirectoryWriters extends DataFlow::CallNode {
40+
DirectoryWriters() {
41+
exists(CdsUtilsModuleAccess utils |
42+
utils.getMember(["mkdirp", "rmdir", "rimraf", "rm"]).getACall() = this
43+
)
44+
}
45+
46+
DataFlow::Node getPath() { this.getAnArgument() = result }
47+
}
48+
49+
class FileReaders extends DataFlow::CallNode {
50+
FileReaders() { exists(CdsUtilsModuleAccess utils | utils.getMember(["read"]).getACall() = this) }
51+
52+
DataFlow::Node getPath() { this.getArgument(0) = result }
53+
}
54+
55+
class FileWriters extends DataFlow::CallNode {
56+
FileWriters() {
57+
exists(CdsUtilsModuleAccess utils | utils.getMember(["append", "write"]).getACall() = this)
58+
}
59+
60+
SourceNode fileReaderWriterUtils(TypeTracker t) {
61+
t.start() and
62+
result = this
63+
or
64+
exists(TypeTracker t2 | result = fileReaderWriterUtils(t2).track(t2, t))
65+
}
66+
67+
SourceNode fileReaderWriterUtils() { result = fileReaderWriterUtils(TypeTracker::end()) }
68+
69+
DataFlow::Node getData() {
70+
this.getNumArgument() = 1 and
71+
this.getArgument(0) = result
72+
or
73+
this.getNumArgument() = 2 and
74+
this.getArgument(1) = result
75+
}
76+
77+
DataFlow::Node getPath() {
78+
fileReaderWriterUtils().getAMemberCall("to").getAnArgument() = result
79+
or
80+
this.getNumArgument() = 2 and
81+
this.getArgument(0) = result
82+
}
83+
}
84+
85+
class FileReaderWriters extends DataFlow::CallNode {
86+
FileReaderWriters() {
87+
exists(CdsUtilsModuleAccess utils | utils.getMember(["copy"]).getACall() = this)
88+
}
89+
90+
SourceNode fileReaderWriterUtils(TypeTracker t) {
91+
t.start() and
92+
result = this
93+
or
94+
exists(TypeTracker t2 | result = fileReaderWriterUtils(t2).track(t2, t))
95+
}
96+
97+
SourceNode fileReaderWriterUtils() { result = fileReaderWriterUtils(TypeTracker::end()) }
98+
99+
DataFlow::Node getPath() {
100+
fileReaderWriterUtils().getAMemberCall("to").getArgument(_) = result
101+
or
102+
this.getAnArgument() = result
103+
}
104+
}

javascript/frameworks/cap/test/models/cds/utils/utils.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@
3535
| utils.js:43:18:43:21 | 'db' | 'db': sink |
3636
| utils.js:43:24:43:29 | 'data' | 'data': sink |
3737
| utils.js:44:10:44:23 | 'dist/db/data' | 'dist/db/data': sink |
38+
| utils.js:52:20:52:28 | 'db/data' | 'db/data': sink |
39+
| utils.js:57:10:57:23 | 'dist/db/data' | 'dist/db/data': sink |

javascript/frameworks/cap/test/models/cds/utils/utils.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,18 @@ await rimraf('dist', 'db', 'data') // sink
4141
await rimraf('dist/db/data') // sink
4242

4343
await rm('dist', 'db', 'data') // sink
44-
await rm('dist/db/data') // sink
44+
await rm('dist/db/data') // sink
45+
46+
function wrapperouter() {
47+
const temp = append
48+
wrapperinnermid(temp)
49+
}
50+
51+
function wrapperinnermid(temp) {
52+
const a = temp('db/data') // sink
53+
wrapperinner(a)
54+
}
55+
56+
function wrapperinner(a) {
57+
a.to('dist/db/data') // sink
58+
}

0 commit comments

Comments
 (0)