From f0ecf1599c417da9996889cd5cff9721c4e4770c Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 26 Nov 2025 10:49:12 +0100 Subject: [PATCH] JS: Add test with file named 'page' --- .../lib/semmle/javascript/frameworks/Next.qll | 16 ++++++++++------ .../ReflectedXss/ReflectedXss.expected | 4 ++++ .../ReflectedXssWithCustomSanitizer.expected | 2 ++ .../CWE-079/ReflectedXss/app/blah/page.jsx | 19 +++++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/app/blah/page.jsx diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll index bdbc18d30f3..8c826f90368 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll @@ -38,20 +38,24 @@ module NextJS { result = appFolder().getAFolder() } + private Folder pagesFolder() { + result = pagesRoot() + or + result = pagesFolder().getAFolder() + } + /** * Gets a "pages" folder in a `Next.js` application. * JavaScript files inside these folders are mapped to routes. */ - Folder getAPagesFolder() { - result = pagesRoot() - or - result = getAPagesFolder().getAFolder() - } + deprecated predicate getAPagesFolder = pagesFolder/0; /** * Gets a module corrosponding to a `Next.js` page. */ - Module getAPagesModule() { result.getFile().getParentContainer() = getAPagesFolder() } + Module getAPagesModule() { + result.getFile() = [pagesFolder().getAFile(), appFolder().getJavaScriptFile("page")] + } /** * Gets a module inside a "pages" folder where `fallback` from `getStaticPaths` is not set to false. diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected index 123ceaecf79..74c8de4686c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXss.expected @@ -35,6 +35,8 @@ | app/api/routeNextRequest.ts:15:20:15:23 | body | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:15:20:15:23 | body | Cross-site scripting vulnerability due to a $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value | | app/api/routeNextRequest.ts:27:20:27:23 | body | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:27:20:27:23 | body | Cross-site scripting vulnerability due to a $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value | | app/api/routeNextRequest.ts:31:27:31:30 | body | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:31:27:31:30 | body | Cross-site scripting vulnerability due to a $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value | +| app/blah/page.jsx:10:13:10:19 | req.url | app/blah/page.jsx:10:13:10:19 | req.url | app/blah/page.jsx:10:13:10:19 | req.url | Cross-site scripting vulnerability due to a $@. | app/blah/page.jsx:10:13:10:19 | req.url | user-provided value | +| app/blah/page.jsx:17:13:17:19 | req.url | app/blah/page.jsx:17:13:17:19 | req.url | app/blah/page.jsx:17:13:17:19 | req.url | Cross-site scripting vulnerability due to a $@. | app/blah/page.jsx:17:13:17:19 | req.url | user-provided value | | app/blah/route.ts:3:25:3:27 | url | app/blah/route.ts:2:17:2:23 | req.url | app/blah/route.ts:3:25:3:27 | url | Cross-site scripting vulnerability due to a $@. | app/blah/route.ts:2:17:2:23 | req.url | user-provided value | | app/pages/Next2.jsx:8:13:8:19 | req.url | app/pages/Next2.jsx:8:13:8:19 | req.url | app/pages/Next2.jsx:8:13:8:19 | req.url | Cross-site scripting vulnerability due to a $@. | app/pages/Next2.jsx:8:13:8:19 | req.url | user-provided value | | app/pages/Next2.jsx:15:13:15:19 | req.url | app/pages/Next2.jsx:15:13:15:19 | req.url | app/pages/Next2.jsx:15:13:15:19 | req.url | Cross-site scripting vulnerability due to a $@. | app/pages/Next2.jsx:15:13:15:19 | req.url | user-provided value | @@ -370,6 +372,8 @@ nodes | app/api/routeNextRequest.ts:15:20:15:23 | body | semmle.label | body | | app/api/routeNextRequest.ts:27:20:27:23 | body | semmle.label | body | | app/api/routeNextRequest.ts:31:27:31:30 | body | semmle.label | body | +| app/blah/page.jsx:10:13:10:19 | req.url | semmle.label | req.url | +| app/blah/page.jsx:17:13:17:19 | req.url | semmle.label | req.url | | app/blah/route.ts:2:11:2:13 | url | semmle.label | url | | app/blah/route.ts:2:17:2:23 | req.url | semmle.label | req.url | | app/blah/route.ts:3:25:3:27 | url | semmle.label | url | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected index b130f70a22f..e55d11371cf 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/ReflectedXssWithCustomSanitizer.expected @@ -34,6 +34,8 @@ | app/api/routeNextRequest.ts:15:20:15:23 | body | Cross-site scripting vulnerability due to $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value | | app/api/routeNextRequest.ts:27:20:27:23 | body | Cross-site scripting vulnerability due to $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value | | app/api/routeNextRequest.ts:31:27:31:30 | body | Cross-site scripting vulnerability due to $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value | +| app/blah/page.jsx:10:13:10:19 | req.url | Cross-site scripting vulnerability due to $@. | app/blah/page.jsx:10:13:10:19 | req.url | user-provided value | +| app/blah/page.jsx:17:13:17:19 | req.url | Cross-site scripting vulnerability due to $@. | app/blah/page.jsx:17:13:17:19 | req.url | user-provided value | | app/blah/route.ts:3:25:3:27 | url | Cross-site scripting vulnerability due to $@. | app/blah/route.ts:2:17:2:23 | req.url | user-provided value | | app/pages/Next2.jsx:8:13:8:19 | req.url | Cross-site scripting vulnerability due to $@. | app/pages/Next2.jsx:8:13:8:19 | req.url | user-provided value | | app/pages/Next2.jsx:15:13:15:19 | req.url | Cross-site scripting vulnerability due to $@. | app/pages/Next2.jsx:15:13:15:19 | req.url | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/app/blah/page.jsx b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/app/blah/page.jsx new file mode 100644 index 00000000000..7df53280636 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss/app/blah/page.jsx @@ -0,0 +1,19 @@ +export default function Page() { + return ; +} + +Page.getInitialProps = async (ctx) => { + const req = ctx.req; + const res = ctx.res; + res.end(req.url); // $ Alert + return {} +} + +export async function getServerSideProps(ctx) { + const req = ctx.req; + const res = ctx.res; + res.end(req.url); // $ Alert + return { + props: {} + } +}