Skip to content

Commit c12c12c

Browse files
committed
Added modeling for react-relay functions that retrieve data.
1 parent 5a1991b commit c12c12c

File tree

3 files changed

+92
-35
lines changed

3 files changed

+92
-35
lines changed

javascript/ql/lib/ext/react-relay-threat.model.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,12 @@ extensions:
44
extensible: sourceModel
55
data:
66
- ["react-relay", "Member[useFragment].ReturnValue", "response"]
7+
- ["react-relay", "Member[useLazyLoadQuery].ReturnValue", "response"]
8+
- ["react-relay", "Member[usePreloadedQuery].ReturnValue", "response"]
9+
- ["react-relay", "Member[useClientQuery].ReturnValue", "response"]
10+
- ["react-relay", "Member[useRefetchableFragment].ReturnValue", "response"]
11+
- ["react-relay", "Member[usePaginationFragment].ReturnValue", "response"]
12+
- ["react-relay", "Member[useMutation].ReturnValue.Member[0].Argument[0].Member[onCompleted].Argument[0]", "response"]
13+
- ["react-relay", "Member[useSubscription].Argument[0].Member[onNext].Argument[0]", "response"]
14+
- ["react-relay", "Member[fetchQuery].ReturnValue.Member[subscribe].Argument[0].Member[next].Argument[0]", "response"]
15+
- ["relay-runtime", "Member[readFragment].ReturnValue", "response"]

javascript/ql/test/query-tests/Security/CWE-079/DomBasedXssWithResponseThreat/Xss.expected

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
#select
22
| test.jsx:27:29:27:32 | data | test.jsx:5:28:5:63 | fetch(" ... ntent") | test.jsx:27:29:27:32 | data | Cross-site scripting vulnerability due to $@. | test.jsx:5:28:5:63 | fetch(" ... ntent") | user-provided value |
33
| testReactRelay.tsx:7:43:7:58 | commentData.text | testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | testReactRelay.tsx:7:43:7:58 | commentData.text | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | user-provided value |
4+
| testReactRelay.tsx:18:48:18:68 | data.co ... 0].text | testReactRelay.tsx:17:16:17:42 | useLazy ... ry, {}) | testReactRelay.tsx:18:48:18:68 | data.co ... 0].text | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:17:16:17:42 | useLazy ... ry, {}) | user-provided value |
5+
| testReactRelay.tsx:28:17:28:67 | usePrel ... r?.name | testReactRelay.tsx:28:17:28:56 | usePrel ... erence) | testReactRelay.tsx:28:17:28:67 | usePrel ... r?.name | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:28:17:28:56 | usePrel ... erence) | user-provided value |
6+
| testReactRelay.tsx:38:49:38:52 | data | testReactRelay.tsx:37:16:37:40 | useClie ... ry, {}) | testReactRelay.tsx:38:49:38:52 | data | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:37:16:37:40 | useClie ... ry, {}) | user-provided value |
7+
| testReactRelay.tsx:47:46:47:49 | data | testReactRelay.tsx:44:27:44:70 | useRefe ... omment) | testReactRelay.tsx:47:46:47:49 | data | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:44:27:44:70 | useRefe ... omment) | user-provided value |
8+
| testReactRelay.tsx:70:49:70:52 | data | testReactRelay.tsx:69:7:69:38 | usePagi ... ry, {}) | testReactRelay.tsx:70:49:70:52 | data | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:69:7:69:38 | usePagi ... ry, {}) | user-provided value |
9+
| testReactRelay.tsx:87:50:87:61 | feedbackText | testReactRelay.tsx:82:17:82:20 | data | testReactRelay.tsx:87:50:87:61 | feedbackText | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:82:17:82:20 | data | user-provided value |
10+
| testReactRelay.tsx:112:48:112:58 | fragmentRef | testReactRelay.tsx:99:14:99:16 | res | testReactRelay.tsx:112:48:112:58 | fragmentRef | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:99:14:99:16 | res | user-provided value |
11+
| testReactRelay.tsx:126:35:126:43 | data.user | testReactRelay.tsx:123:12:123:15 | data | testReactRelay.tsx:126:35:126:43 | data.user | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:123:12:123:15 | data | user-provided value |
12+
| testReactRelay.tsx:136:50:136:53 | data | testReactRelay.tsx:135:16:135:39 | readFra ... y, key) | testReactRelay.tsx:136:50:136:53 | data | Cross-site scripting vulnerability due to $@. | testReactRelay.tsx:135:16:135:39 | readFra ... y, key) | user-provided value |
413
edges
514
| test.jsx:5:11:5:63 | response | test.jsx:6:24:6:31 | response | provenance | |
615
| test.jsx:5:22:5:63 | await f ... ntent") | test.jsx:5:11:5:63 | response | provenance | |
@@ -14,6 +23,30 @@ edges
1423
| testReactRelay.tsx:5:9:5:52 | commentData | testReactRelay.tsx:7:43:7:53 | commentData | provenance | |
1524
| testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | testReactRelay.tsx:5:9:5:52 | commentData | provenance | |
1625
| testReactRelay.tsx:7:43:7:53 | commentData | testReactRelay.tsx:7:43:7:58 | commentData.text | provenance | |
26+
| testReactRelay.tsx:17:9:17:42 | data | testReactRelay.tsx:18:48:18:51 | data | provenance | |
27+
| testReactRelay.tsx:17:16:17:42 | useLazy ... ry, {}) | testReactRelay.tsx:17:9:17:42 | data | provenance | |
28+
| testReactRelay.tsx:18:48:18:51 | data | testReactRelay.tsx:18:48:18:68 | data.co ... 0].text | provenance | |
29+
| testReactRelay.tsx:28:17:28:56 | usePrel ... erence) | testReactRelay.tsx:28:17:28:67 | usePrel ... r?.name | provenance | |
30+
| testReactRelay.tsx:37:9:37:40 | data | testReactRelay.tsx:38:49:38:52 | data | provenance | |
31+
| testReactRelay.tsx:37:16:37:40 | useClie ... ry, {}) | testReactRelay.tsx:37:9:37:40 | data | provenance | |
32+
| testReactRelay.tsx:44:9:44:23 | [data, refetch] | testReactRelay.tsx:44:9:44:70 | data | provenance | |
33+
| testReactRelay.tsx:44:9:44:70 | data | testReactRelay.tsx:47:46:47:49 | data | provenance | |
34+
| testReactRelay.tsx:44:27:44:70 | useRefe ... omment) | testReactRelay.tsx:44:9:44:23 | [data, refetch] | provenance | |
35+
| testReactRelay.tsx:60:9:69:3 | {\\n d ... ch,\\n } | testReactRelay.tsx:60:9:69:38 | data | provenance | |
36+
| testReactRelay.tsx:60:9:69:38 | data | testReactRelay.tsx:70:49:70:52 | data | provenance | |
37+
| testReactRelay.tsx:69:7:69:38 | usePagi ... ry, {}) | testReactRelay.tsx:60:9:69:3 | {\\n d ... ch,\\n } | provenance | |
38+
| testReactRelay.tsx:79:9:79:54 | feedbackText | testReactRelay.tsx:87:50:87:61 | feedbackText | provenance | |
39+
| testReactRelay.tsx:79:10:79:21 | feedbackText | testReactRelay.tsx:79:9:79:54 | feedbackText | provenance | |
40+
| testReactRelay.tsx:82:17:82:20 | data | testReactRelay.tsx:83:23:83:26 | data | provenance | |
41+
| testReactRelay.tsx:83:23:83:26 | data | testReactRelay.tsx:79:10:79:21 | feedbackText | provenance | |
42+
| testReactRelay.tsx:94:9:94:50 | fragmentRef | testReactRelay.tsx:112:48:112:58 | fragmentRef | provenance | |
43+
| testReactRelay.tsx:94:10:94:20 | fragmentRef | testReactRelay.tsx:94:9:94:50 | fragmentRef | provenance | |
44+
| testReactRelay.tsx:99:14:99:16 | res | testReactRelay.tsx:100:22:100:24 | res | provenance | |
45+
| testReactRelay.tsx:100:22:100:24 | res | testReactRelay.tsx:94:10:94:20 | fragmentRef | provenance | |
46+
| testReactRelay.tsx:123:12:123:15 | data | testReactRelay.tsx:126:35:126:38 | data | provenance | |
47+
| testReactRelay.tsx:126:35:126:38 | data | testReactRelay.tsx:126:35:126:43 | data.user | provenance | |
48+
| testReactRelay.tsx:135:9:135:39 | data | testReactRelay.tsx:136:50:136:53 | data | provenance | |
49+
| testReactRelay.tsx:135:16:135:39 | readFra ... y, key) | testReactRelay.tsx:135:9:135:39 | data | provenance | |
1750
nodes
1851
| test.jsx:5:11:5:63 | response | semmle.label | response |
1952
| test.jsx:5:22:5:63 | await f ... ntent") | semmle.label | await f ... ntent") |
@@ -29,22 +62,37 @@ nodes
2962
| testReactRelay.tsx:5:23:5:52 | useFrag ... entRef) | semmle.label | useFrag ... entRef) |
3063
| testReactRelay.tsx:7:43:7:53 | commentData | semmle.label | commentData |
3164
| testReactRelay.tsx:7:43:7:58 | commentData.text | semmle.label | commentData.text |
65+
| testReactRelay.tsx:17:9:17:42 | data | semmle.label | data |
66+
| testReactRelay.tsx:17:16:17:42 | useLazy ... ry, {}) | semmle.label | useLazy ... ry, {}) |
67+
| testReactRelay.tsx:18:48:18:51 | data | semmle.label | data |
68+
| testReactRelay.tsx:18:48:18:68 | data.co ... 0].text | semmle.label | data.co ... 0].text |
69+
| testReactRelay.tsx:28:17:28:56 | usePrel ... erence) | semmle.label | usePrel ... erence) |
70+
| testReactRelay.tsx:28:17:28:67 | usePrel ... r?.name | semmle.label | usePrel ... r?.name |
71+
| testReactRelay.tsx:37:9:37:40 | data | semmle.label | data |
72+
| testReactRelay.tsx:37:16:37:40 | useClie ... ry, {}) | semmle.label | useClie ... ry, {}) |
73+
| testReactRelay.tsx:38:49:38:52 | data | semmle.label | data |
74+
| testReactRelay.tsx:44:9:44:23 | [data, refetch] | semmle.label | [data, refetch] |
75+
| testReactRelay.tsx:44:9:44:70 | data | semmle.label | data |
76+
| testReactRelay.tsx:44:27:44:70 | useRefe ... omment) | semmle.label | useRefe ... omment) |
77+
| testReactRelay.tsx:47:46:47:49 | data | semmle.label | data |
78+
| testReactRelay.tsx:60:9:69:3 | {\\n d ... ch,\\n } | semmle.label | {\\n d ... ch,\\n } |
79+
| testReactRelay.tsx:60:9:69:38 | data | semmle.label | data |
80+
| testReactRelay.tsx:69:7:69:38 | usePagi ... ry, {}) | semmle.label | usePagi ... ry, {}) |
81+
| testReactRelay.tsx:70:49:70:52 | data | semmle.label | data |
82+
| testReactRelay.tsx:79:9:79:54 | feedbackText | semmle.label | feedbackText |
83+
| testReactRelay.tsx:79:10:79:21 | feedbackText | semmle.label | feedbackText |
84+
| testReactRelay.tsx:82:17:82:20 | data | semmle.label | data |
85+
| testReactRelay.tsx:83:23:83:26 | data | semmle.label | data |
86+
| testReactRelay.tsx:87:50:87:61 | feedbackText | semmle.label | feedbackText |
87+
| testReactRelay.tsx:94:9:94:50 | fragmentRef | semmle.label | fragmentRef |
88+
| testReactRelay.tsx:94:10:94:20 | fragmentRef | semmle.label | fragmentRef |
89+
| testReactRelay.tsx:99:14:99:16 | res | semmle.label | res |
90+
| testReactRelay.tsx:100:22:100:24 | res | semmle.label | res |
91+
| testReactRelay.tsx:112:48:112:58 | fragmentRef | semmle.label | fragmentRef |
92+
| testReactRelay.tsx:123:12:123:15 | data | semmle.label | data |
93+
| testReactRelay.tsx:126:35:126:38 | data | semmle.label | data |
94+
| testReactRelay.tsx:126:35:126:43 | data.user | semmle.label | data.user |
95+
| testReactRelay.tsx:135:9:135:39 | data | semmle.label | data |
96+
| testReactRelay.tsx:135:16:135:39 | readFra ... y, key) | semmle.label | readFra ... y, key) |
97+
| testReactRelay.tsx:136:50:136:53 | data | semmle.label | data |
3298
subpaths
33-
testFailures
34-
| testReactRelay.tsx:17:45:17:64 | // $ Missing: Source | Missing result: Source |
35-
| testReactRelay.tsx:18:77:18:95 | // $ Missing: Alert | Missing result: Alert |
36-
| testReactRelay.tsx:28:70:28:88 | // $ Missing: Alert | Missing result: Alert |
37-
| testReactRelay.tsx:37:43:37:62 | // $ Missing: Source | Missing result: Source |
38-
| testReactRelay.tsx:38:61:38:79 | // $ Missing: Alert | Missing result: Alert |
39-
| testReactRelay.tsx:44:73:44:92 | // $ Missing: Source | Missing result: Source |
40-
| testReactRelay.tsx:47:57:47:75 | // $ Missing: Alert | Missing result: Alert |
41-
| testReactRelay.tsx:69:41:69:60 | // $ Missing: Source | Missing result: Source |
42-
| testReactRelay.tsx:70:61:70:79 | // $ Missing: Alert | Missing result: Alert |
43-
| testReactRelay.tsx:82:25:82:44 | // $ Missing: Source | Missing result: Source |
44-
| testReactRelay.tsx:87:71:87:89 | // $ Missing: Alert | Missing result: Alert |
45-
| testReactRelay.tsx:99:24:99:43 | // $ Missing: Source | Missing result: Source |
46-
| testReactRelay.tsx:112:68:112:86 | // $ Missing: Alert | Missing result: Alert |
47-
| testReactRelay.tsx:123:23:123:42 | // $ Missing: Source | Missing result: Source |
48-
| testReactRelay.tsx:126:46:126:64 | // $ Missing: Alert | Missing result: Alert |
49-
| testReactRelay.tsx:135:42:135:61 | // $ Missing: Source | Missing result: Source |
50-
| testReactRelay.tsx:136:63:136:81 | // $ Missing: Alert | Missing result: Alert |

javascript/ql/test/query-tests/Security/CWE-079/DomBasedXssWithResponseThreat/testReactRelay.tsx

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ const func1 = ({ commentRef, query }) => {
1414
import { useLazyLoadQuery } from "react-relay";
1515

1616
function func2({ query }) {
17-
const data = useLazyLoadQuery(query, {}); // $ Missing: Source
18-
return <p dangerouslySetInnerHTML={{ __html: data.comments[0].text }} />; // $ Missing: Alert
17+
const data = useLazyLoadQuery(query, {}); // $ Source
18+
return <p dangerouslySetInnerHTML={{ __html: data.comments[0].text }} />; // $ Alert
1919
}
2020

2121
import { useQueryLoader, usePreloadedQuery } from "react-relay";
@@ -25,7 +25,7 @@ function func3({ initialQueryRef, query }) {
2525
return (
2626
<h1
2727
dangerouslySetInnerHTML={{
28-
__html: usePreloadedQuery(query, queryReference).user?.name, // $ Missing: Alert
28+
__html: usePreloadedQuery(query, queryReference).user?.name, // $ Alert
2929
}}
3030
/>
3131
);
@@ -34,17 +34,17 @@ function func3({ initialQueryRef, query }) {
3434
import { useClientQuery } from "react-relay";
3535

3636
function func4({ query }) {
37-
const data = useClientQuery(query, {}); // $ Missing: Source
38-
return <h1 dangerouslySetInnerHTML={{ __html: data }} />; // $ Missing: Alert
37+
const data = useClientQuery(query, {}); // $ Source
38+
return <h1 dangerouslySetInnerHTML={{ __html: data }} />; // $ Alert
3939
}
4040

4141
import { useRefetchableFragment } from "react-relay";
4242

4343
function func5({ query, props }) {
44-
const [data, refetch] = useRefetchableFragment(query, props.comment); // $ Missing: Source
44+
const [data, refetch] = useRefetchableFragment(query, props.comment); // $ Source
4545
return (
4646
<>
47-
<h1 dangerouslySetInnerHTML={{ __html: data }} /> // $ Missing: Alert
47+
<h1 dangerouslySetInnerHTML={{ __html: data }} /> // $ Alert
4848
<Button
4949
onClick={() => {
5050
refetch({ lang: "SPANISH" }, { fetchPolicy: "store-or-network" });
@@ -66,8 +66,8 @@ function func6({ query }) {
6666
isLoadingNext,
6767
isLoadingPrevious,
6868
refetch,
69-
} = usePaginationFragment(query, {}); // $ Missing: Source
70-
return <h1 dangerouslySetInnerHTML={{ __html: data }} />; // $ Missing: Alert
69+
} = usePaginationFragment(query, {}); // $ Source
70+
return <h1 dangerouslySetInnerHTML={{ __html: data }} />; // $ Alert
7171
}
7272

7373

@@ -79,12 +79,12 @@ function func7(query) {
7979
const [feedbackText, setFeedbackText] = useState('');
8080

8181
commit({
82-
onCompleted(data) { // $ Missing: Source
82+
onCompleted(data) { // $ Source
8383
setFeedbackText(data);
8484
},
8585
});
8686

87-
return (<div dangerouslySetInnerHTML={{__html: feedbackText, }}/>); // $ Missing: Alert
87+
return (<div dangerouslySetInnerHTML={{__html: feedbackText, }}/>); // $ Alert
8888
}
8989

9090
import { useSubscription } from 'react-relay';
@@ -96,7 +96,7 @@ function func8({GroupLessonsSubscription}) {
9696
const groupLessonConfig = useMemo(() => ({
9797
subscription: GroupLessonsSubscription,
9898
variables: {},
99-
onNext: (res) => { // $ Missing: Source
99+
onNext: (res) => { // $ Source
100100
setFragmentRef(res);
101101
},
102102
onError: (err) => {
@@ -109,7 +109,7 @@ function func8({GroupLessonsSubscription}) {
109109

110110
useSubscription(groupLessonConfig);
111111

112-
return (<div dangerouslySetInnerHTML={{__html: fragmentRef, }}/>); // $ Missing: Alert
112+
return (<div dangerouslySetInnerHTML={{__html: fragmentRef, }}/>); // $ Alert
113113
}
114114

115115

@@ -120,10 +120,10 @@ function func9({query, environment}) {
120120
start: () => {},
121121
complete: () => {},
122122
error: (error) => {},
123-
next: (data) => { // $ Missing: Source
123+
next: (data) => { // $ Source
124124
const outputElement = document.getElementById('output');
125125
if (outputElement) {
126-
outputElement.innerHTML = data.user; // $ Missing: Alert
126+
outputElement.innerHTML = data.user; // $ Alert
127127
}
128128
}
129129
});
@@ -132,6 +132,6 @@ function func9({query, environment}) {
132132
import { readFragment } from "relay-runtime";
133133

134134
function func10({ query, key }) {
135-
const data = readFragment(query, key); // $ Missing: Source
136-
return (<h1 dangerouslySetInnerHTML={{ __html: data }} />); // $ Missing: Alert
135+
const data = readFragment(query, key); // $ Source
136+
return (<h1 dangerouslySetInnerHTML={{ __html: data }} />); // $ Alert
137137
}

0 commit comments

Comments
 (0)