Skip to content

Commit 41a0c0b

Browse files
committed
support React links in js/client-side-unvalidated-url-redirection
1 parent 79839d2 commit 41a0c0b

File tree

4 files changed

+33
-5
lines changed

4 files changed

+33
-5
lines changed

javascript/ql/src/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,15 @@ module ClientSideUrlRedirect {
166166
)
167167
}
168168
}
169+
170+
/**
171+
* A write to an React attribute which may execute JavaScript code.
172+
*/
173+
class ReactAttributeWriteUrlSink extends ScriptUrlSink {
174+
ReactAttributeWriteUrlSink() {
175+
exists(JSXAttribute attr | attr.getName() = propertyNameIsInterpretedAsJavaScriptUrl() |
176+
this = attr.getValue().flow()
177+
)
178+
}
179+
}
169180
}

javascript/ql/src/semmle/javascript/security/dataflow/DOM.qll

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,17 @@ class DomPropWriteNode extends Assignment {
122122
* Holds if the assigned value is interpreted as JavaScript via javascript: protocol.
123123
*/
124124
predicate interpretsValueAsJavaScriptUrl() {
125-
lhs.getPropertyName() = "action" or
126-
lhs.getPropertyName() = "formaction" or
127-
lhs.getPropertyName() = "href" or
128-
lhs.getPropertyName() = "src" or
129-
lhs.getPropertyName() = "data"
125+
lhs.getPropertyName() = propertyNameIsInterpretedAsJavaScriptUrl()
130126
}
131127
}
132128

129+
/**
130+
* Holds if a value assigned to property `name` of a DOM node can be interpreted as JavaScript via the `javascript:` protocol.
131+
*/
132+
string propertyNameIsInterpretedAsJavaScriptUrl() {
133+
result = ["action", "formaction", "href", "src", "data"]
134+
}
135+
133136
/**
134137
* A value written to web storage, like `localStorage` or `sessionStorage`.
135138
*/

javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ nodes
77
| react.js:10:60:10:76 | document.location |
88
| react.js:10:60:10:81 | documen ... on.hash |
99
| react.js:10:60:10:81 | documen ... on.hash |
10+
| react.js:21:24:21:40 | document.location |
11+
| react.js:21:24:21:40 | document.location |
12+
| react.js:21:24:21:45 | documen ... on.hash |
13+
| react.js:21:24:21:45 | documen ... on.hash |
1014
| sanitizer.js:2:9:2:25 | url |
1115
| sanitizer.js:2:15:2:25 | window.name |
1216
| sanitizer.js:2:15:2:25 | window.name |
@@ -197,6 +201,10 @@ edges
197201
| react.js:10:60:10:76 | document.location | react.js:10:60:10:81 | documen ... on.hash |
198202
| react.js:10:60:10:76 | document.location | react.js:10:60:10:81 | documen ... on.hash |
199203
| react.js:10:60:10:76 | document.location | react.js:10:60:10:81 | documen ... on.hash |
204+
| react.js:21:24:21:40 | document.location | react.js:21:24:21:45 | documen ... on.hash |
205+
| react.js:21:24:21:40 | document.location | react.js:21:24:21:45 | documen ... on.hash |
206+
| react.js:21:24:21:40 | document.location | react.js:21:24:21:45 | documen ... on.hash |
207+
| react.js:21:24:21:40 | document.location | react.js:21:24:21:45 | documen ... on.hash |
200208
| sanitizer.js:2:9:2:25 | url | sanitizer.js:4:27:4:29 | url |
201209
| sanitizer.js:2:9:2:25 | url | sanitizer.js:4:27:4:29 | url |
202210
| sanitizer.js:2:9:2:25 | url | sanitizer.js:16:27:16:29 | url |
@@ -367,6 +375,7 @@ edges
367375
#select
368376
| electron.js:7:20:7:29 | getTaint() | electron.js:4:12:4:22 | window.name | electron.js:7:20:7:29 | getTaint() | Untrusted URL redirection due to $@. | electron.js:4:12:4:22 | window.name | user-provided value |
369377
| react.js:10:60:10:81 | documen ... on.hash | react.js:10:60:10:76 | document.location | react.js:10:60:10:81 | documen ... on.hash | Untrusted URL redirection due to $@. | react.js:10:60:10:76 | document.location | user-provided value |
378+
| react.js:21:24:21:45 | documen ... on.hash | react.js:21:24:21:40 | document.location | react.js:21:24:21:45 | documen ... on.hash | Untrusted URL redirection due to $@. | react.js:21:24:21:40 | document.location | user-provided value |
370379
| sanitizer.js:4:27:4:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:4:27:4:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
371380
| sanitizer.js:16:27:16:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:16:27:16:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
372381
| sanitizer.js:19:27:19:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:19:27:19:29 | url | Untrusted URL redirection due to $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |

javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/react.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,8 @@ class Application extends React.Component {
1515
};
1616

1717
export default Application
18+
19+
import Link from 'next/link'
20+
export function NextLink() {
21+
return <Link href={document.location.hash}><a>this page!</a></Link>;
22+
}

0 commit comments

Comments
 (0)