Skip to content

Commit 232893a

Browse files
committed
make query parameters in ServerSideProps and next/router
as a RemoteFlowSource
1 parent 1f4fc7f commit 232893a

File tree

3 files changed

+92
-4
lines changed

3 files changed

+92
-4
lines changed

javascript/ql/lib/semmle/javascript/frameworks/Next.qll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ module NextJS {
5353
.getAFunctionValue()
5454
.getParameter(0)
5555
.getAPropertyRead("params")
56+
or
57+
exists(DataFlow::ParameterNode params |
58+
params = getServerSidePropsFunction(_).getParameter(0)
59+
|
60+
this = params.getAPropertyRead("params") or
61+
this = params.getAPropertyRead("query")
62+
)
63+
or
64+
this = nextRouter().getAPropertyRead("query")
5665
}
5766

5867
override string getSourceType() { result = "Next request parameter" }

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

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,38 @@ nodes
504504
| optionalSanitizer.js:45:29:45:47 | sanitizeBad(target) |
505505
| optionalSanitizer.js:45:41:45:46 | target |
506506
| optionalSanitizer.js:45:51:45:56 | target |
507+
| pages/[id].jsx:5:9:5:14 | { id } |
508+
| pages/[id].jsx:5:9:5:14 | { id } |
509+
| pages/[id].jsx:5:9:5:29 | id |
510+
| pages/[id].jsx:5:9:5:29 | id |
511+
| pages/[id].jsx:5:11:5:12 | id |
512+
| pages/[id].jsx:5:11:5:12 | id |
513+
| pages/[id].jsx:5:18:5:29 | router.query |
514+
| pages/[id].jsx:5:18:5:29 | router.query |
515+
| pages/[id].jsx:5:18:5:29 | router.query |
516+
| pages/[id].jsx:10:44:10:45 | id |
517+
| pages/[id].jsx:10:44:10:45 | id |
518+
| pages/[id].jsx:10:44:10:45 | id |
519+
| pages/[id].jsx:13:44:13:52 | params.id |
520+
| pages/[id].jsx:13:44:13:52 | params.id |
521+
| pages/[id].jsx:13:44:13:52 | params.id |
522+
| pages/[id].jsx:16:44:16:51 | params.q |
523+
| pages/[id].jsx:16:44:16:51 | params.q |
524+
| pages/[id].jsx:16:44:16:51 | params.q |
525+
| pages/[id].jsx:25:11:25:24 | context.params |
526+
| pages/[id].jsx:25:11:25:24 | context.params |
527+
| pages/[id].jsx:25:11:25:24 | context.params |
528+
| pages/[id].jsx:25:11:25:27 | context.params.id |
529+
| pages/[id].jsx:25:11:25:27 | context.params.id |
530+
| pages/[id].jsx:25:11:25:33 | context ... d \|\| "" |
531+
| pages/[id].jsx:25:11:25:33 | context ... d \|\| "" |
532+
| pages/[id].jsx:26:10:26:22 | context.query |
533+
| pages/[id].jsx:26:10:26:22 | context.query |
534+
| pages/[id].jsx:26:10:26:22 | context.query |
535+
| pages/[id].jsx:26:10:26:30 | context ... .foobar |
536+
| pages/[id].jsx:26:10:26:30 | context ... .foobar |
537+
| pages/[id].jsx:26:10:26:36 | context ... r \|\| "" |
538+
| pages/[id].jsx:26:10:26:36 | context ... r \|\| "" |
507539
| react-native.js:7:7:7:33 | tainted |
508540
| react-native.js:7:7:7:33 | tainted |
509541
| react-native.js:7:17:7:33 | req.param("code") |
@@ -1604,6 +1636,38 @@ edges
16041636
| optionalSanitizer.js:45:41:45:46 | target | optionalSanitizer.js:45:29:45:47 | sanitizeBad(target) |
16051637
| optionalSanitizer.js:45:51:45:56 | target | optionalSanitizer.js:45:18:45:56 | sanitiz ... target |
16061638
| optionalSanitizer.js:45:51:45:56 | target | optionalSanitizer.js:45:18:45:56 | sanitiz ... target |
1639+
| pages/[id].jsx:5:9:5:14 | { id } | pages/[id].jsx:5:11:5:12 | id |
1640+
| pages/[id].jsx:5:9:5:14 | { id } | pages/[id].jsx:5:11:5:12 | id |
1641+
| pages/[id].jsx:5:9:5:29 | id | pages/[id].jsx:10:44:10:45 | id |
1642+
| pages/[id].jsx:5:9:5:29 | id | pages/[id].jsx:10:44:10:45 | id |
1643+
| pages/[id].jsx:5:9:5:29 | id | pages/[id].jsx:10:44:10:45 | id |
1644+
| pages/[id].jsx:5:9:5:29 | id | pages/[id].jsx:10:44:10:45 | id |
1645+
| pages/[id].jsx:5:11:5:12 | id | pages/[id].jsx:5:9:5:29 | id |
1646+
| pages/[id].jsx:5:11:5:12 | id | pages/[id].jsx:5:9:5:29 | id |
1647+
| pages/[id].jsx:5:18:5:29 | router.query | pages/[id].jsx:5:9:5:14 | { id } |
1648+
| pages/[id].jsx:5:18:5:29 | router.query | pages/[id].jsx:5:9:5:14 | { id } |
1649+
| pages/[id].jsx:5:18:5:29 | router.query | pages/[id].jsx:5:9:5:14 | { id } |
1650+
| pages/[id].jsx:5:18:5:29 | router.query | pages/[id].jsx:5:9:5:14 | { id } |
1651+
| pages/[id].jsx:25:11:25:24 | context.params | pages/[id].jsx:25:11:25:27 | context.params.id |
1652+
| pages/[id].jsx:25:11:25:24 | context.params | pages/[id].jsx:25:11:25:27 | context.params.id |
1653+
| pages/[id].jsx:25:11:25:24 | context.params | pages/[id].jsx:25:11:25:27 | context.params.id |
1654+
| pages/[id].jsx:25:11:25:24 | context.params | pages/[id].jsx:25:11:25:27 | context.params.id |
1655+
| pages/[id].jsx:25:11:25:27 | context.params.id | pages/[id].jsx:25:11:25:33 | context ... d \|\| "" |
1656+
| pages/[id].jsx:25:11:25:27 | context.params.id | pages/[id].jsx:25:11:25:33 | context ... d \|\| "" |
1657+
| pages/[id].jsx:25:11:25:33 | context ... d \|\| "" | pages/[id].jsx:13:44:13:52 | params.id |
1658+
| pages/[id].jsx:25:11:25:33 | context ... d \|\| "" | pages/[id].jsx:13:44:13:52 | params.id |
1659+
| pages/[id].jsx:25:11:25:33 | context ... d \|\| "" | pages/[id].jsx:13:44:13:52 | params.id |
1660+
| pages/[id].jsx:25:11:25:33 | context ... d \|\| "" | pages/[id].jsx:13:44:13:52 | params.id |
1661+
| pages/[id].jsx:26:10:26:22 | context.query | pages/[id].jsx:26:10:26:30 | context ... .foobar |
1662+
| pages/[id].jsx:26:10:26:22 | context.query | pages/[id].jsx:26:10:26:30 | context ... .foobar |
1663+
| pages/[id].jsx:26:10:26:22 | context.query | pages/[id].jsx:26:10:26:30 | context ... .foobar |
1664+
| pages/[id].jsx:26:10:26:22 | context.query | pages/[id].jsx:26:10:26:30 | context ... .foobar |
1665+
| pages/[id].jsx:26:10:26:30 | context ... .foobar | pages/[id].jsx:26:10:26:36 | context ... r \|\| "" |
1666+
| pages/[id].jsx:26:10:26:30 | context ... .foobar | pages/[id].jsx:26:10:26:36 | context ... r \|\| "" |
1667+
| pages/[id].jsx:26:10:26:36 | context ... r \|\| "" | pages/[id].jsx:16:44:16:51 | params.q |
1668+
| pages/[id].jsx:26:10:26:36 | context ... r \|\| "" | pages/[id].jsx:16:44:16:51 | params.q |
1669+
| pages/[id].jsx:26:10:26:36 | context ... r \|\| "" | pages/[id].jsx:16:44:16:51 | params.q |
1670+
| pages/[id].jsx:26:10:26:36 | context ... r \|\| "" | pages/[id].jsx:16:44:16:51 | params.q |
16071671
| react-native.js:7:7:7:33 | tainted | react-native.js:8:18:8:24 | tainted |
16081672
| react-native.js:7:7:7:33 | tainted | react-native.js:8:18:8:24 | tainted |
16091673
| react-native.js:7:7:7:33 | tainted | react-native.js:8:18:8:24 | tainted |
@@ -2287,6 +2351,9 @@ edges
22872351
| optionalSanitizer.js:39:18:39:25 | tainted3 | optionalSanitizer.js:26:16:26:39 | documen ... .search | optionalSanitizer.js:39:18:39:25 | tainted3 | Cross-site scripting vulnerability due to $@. | optionalSanitizer.js:26:16:26:39 | documen ... .search | user-provided value |
22882352
| optionalSanitizer.js:43:18:43:25 | tainted3 | optionalSanitizer.js:26:16:26:39 | documen ... .search | optionalSanitizer.js:43:18:43:25 | tainted3 | Cross-site scripting vulnerability due to $@. | optionalSanitizer.js:26:16:26:39 | documen ... .search | user-provided value |
22892353
| optionalSanitizer.js:45:18:45:56 | sanitiz ... target | optionalSanitizer.js:26:16:26:39 | documen ... .search | optionalSanitizer.js:45:18:45:56 | sanitiz ... target | Cross-site scripting vulnerability due to $@. | optionalSanitizer.js:26:16:26:39 | documen ... .search | user-provided value |
2354+
| pages/[id].jsx:10:44:10:45 | id | pages/[id].jsx:5:18:5:29 | router.query | pages/[id].jsx:10:44:10:45 | id | Cross-site scripting vulnerability due to $@. | pages/[id].jsx:5:18:5:29 | router.query | user-provided value |
2355+
| pages/[id].jsx:13:44:13:52 | params.id | pages/[id].jsx:25:11:25:24 | context.params | pages/[id].jsx:13:44:13:52 | params.id | Cross-site scripting vulnerability due to $@. | pages/[id].jsx:25:11:25:24 | context.params | user-provided value |
2356+
| pages/[id].jsx:16:44:16:51 | params.q | pages/[id].jsx:26:10:26:22 | context.query | pages/[id].jsx:16:44:16:51 | params.q | Cross-site scripting vulnerability due to $@. | pages/[id].jsx:26:10:26:22 | context.query | user-provided value |
22902357
| react-native.js:8:18:8:24 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:18:8:24 | tainted | Cross-site scripting vulnerability due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
22912358
| react-native.js:9:27:9:33 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:9:27:9:33 | tainted | Cross-site scripting vulnerability due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
22922359
| react-use-context.js:10:22:10:32 | window.name | react-use-context.js:10:22:10:32 | window.name | react-use-context.js:10:22:10:32 | window.name | Cross-site scripting vulnerability due to $@. | react-use-context.js:10:22:10:32 | window.name | user-provided value |

javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/pages/[id].jsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
1-
export default function Post({ id, q }) {
1+
import { useRouter } from 'next/router'
2+
3+
export default function Post(params) {
4+
const router = useRouter()
5+
const { id } = router.query
6+
27
return (
38
<>
4-
<div dangerouslySetInnerHTML={{__html: id }} />
5-
<div dangerouslySetInnerHTML={{__html: q }} />
9+
<div
10+
dangerouslySetInnerHTML={{ __html: id }} // NOT OK
11+
/>
12+
<div
13+
dangerouslySetInnerHTML={{ __html: params.id }} // NOT OK
14+
/>
15+
<div
16+
dangerouslySetInnerHTML={{ __html: params.q }} // NOT OK
17+
/>
618
</>
719
)
820
}
921

1022
export async function getServerSideProps(context) {
1123
return {
1224
props: {
13-
id: context.params?.id || "",
25+
id: context.params.id || "",
1426
q: context.query?.foobar || "",
1527
}
1628
}

0 commit comments

Comments
 (0)