mirror of
https://github.com/github/codeql.git
synced 2026-05-01 19:55:15 +02:00
support Next.js page request/response objects
This commit is contained in:
@@ -7,7 +7,8 @@ import javascript
|
||||
/**
|
||||
* Provides classes and predicates modelling [Next.js](https://www.npmjs.com/package/next).
|
||||
*/
|
||||
private module NextJS {
|
||||
module NextJS {
|
||||
// TODO: Private.
|
||||
/**
|
||||
* Gets a `package.json` that depends on the `Next.js` library.
|
||||
*/
|
||||
@@ -59,6 +60,41 @@ private module NextJS {
|
||||
override string getSourceType() { result = "Next request parameter" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `getStaticProps` function in a Next.js page.
|
||||
* This function is executed at build time, or when a page with a new URL is requested for the first time (if `fallback` is not false).
|
||||
*/
|
||||
DataFlow::FunctionNode getStaticPropsFunction(Module pageModule) {
|
||||
pageModule = getAPagesModule() and
|
||||
result = pageModule.getAnExportedValue("getStaticProps").getAFunctionValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `getServerSideProps` function in a Next.js page.
|
||||
* This function is executed on the server every time a request for the page is made.
|
||||
* The function receives a context parameter, which includes HTTP request/response objects.
|
||||
*/
|
||||
DataFlow::FunctionNode getServerSidePropsFunction(Module pageModule) {
|
||||
pageModule = getAPagesModule() and
|
||||
result = pageModule.getAnExportedValue("getServerSideProps").getAFunctionValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `getInitialProps` function in a Next.js page.
|
||||
* This function is executed on the server every time a request for the page is made.
|
||||
* The function receives a context parameter, which includes HTTP request/response objects.
|
||||
*/
|
||||
DataFlow::FunctionNode getInitialProps(Module pageModule) {
|
||||
pageModule = getAPagesModule() and
|
||||
result =
|
||||
pageModule
|
||||
.getAnExportedValue("default")
|
||||
.getAFunctionValue()
|
||||
.getAPropertyWrite("getInitialProps")
|
||||
.getRhs()
|
||||
.getAFunctionValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* A step modelling the flow from the server-computed `getStaticProps` to the server/client rendering of the page.
|
||||
*/
|
||||
@@ -73,17 +109,48 @@ private module NextJS {
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
(
|
||||
pred =
|
||||
pageModule
|
||||
.getAnExportedValue(["getStaticProps", "getServerSideProps"])
|
||||
.getAFunctionValue()
|
||||
[getStaticPropsFunction(pageModule), getServerSidePropsFunction(pageModule)]
|
||||
.getAReturn()
|
||||
.getALocalSource()
|
||||
.getAPropertyWrite("props")
|
||||
.getRhs()
|
||||
or
|
||||
pred = this.getAPropertyWrite("getInitialProps").getRhs().getAFunctionValue().getAReturn()
|
||||
pred = getInitialProps(pageModule).getAReturn()
|
||||
) and
|
||||
succ = this.getParameter(0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Next.js function that is exected on the server for every request, seen as a routehandler.
|
||||
*/
|
||||
class NextHttpRouteHandler extends HTTP::Servers::StandardRouteHandler, DataFlow::FunctionNode {
|
||||
Module pageModule;
|
||||
|
||||
NextHttpRouteHandler() {
|
||||
this = getServerSidePropsFunction(pageModule) or this = getInitialProps(pageModule)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A NodeJS HTTP request object in a Next.js page.
|
||||
*/
|
||||
class NextHttpRequestSource extends NodeJSLib::RequestSource {
|
||||
NextHttpRouteHandler rh;
|
||||
|
||||
NextHttpRequestSource() { this = rh.getParameter(0).getAPropertyRead("req") }
|
||||
|
||||
override HTTP::RouteHandler getRouteHandler() { result = rh }
|
||||
}
|
||||
|
||||
/**
|
||||
* A NodeJS HTTP response object in a Next.js page.
|
||||
*/
|
||||
class NextHttpResponseSource extends NodeJSLib::ResponseSource {
|
||||
NextHttpRouteHandler rh;
|
||||
|
||||
NextHttpResponseSource() { this = rh.getParameter(0).getAPropertyRead("res") }
|
||||
|
||||
override HTTP::RouteHandler getRouteHandler() { result = rh }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,13 +107,18 @@ module NodeJSLib {
|
||||
}
|
||||
|
||||
/**
|
||||
* A Node.js response source, that is, the response parameter of a
|
||||
* A Node.js response source.
|
||||
*/
|
||||
abstract class ResponseSource extends HTTP::Servers::ResponseSource { }
|
||||
|
||||
/**
|
||||
* A standard Node.js response source, that is, the response parameter of a
|
||||
* route handler.
|
||||
*/
|
||||
private class ResponseSource extends HTTP::Servers::ResponseSource {
|
||||
private class StandardResponseSource extends ResponseSource {
|
||||
RouteHandler rh;
|
||||
|
||||
ResponseSource() { this = DataFlow::parameterNode(rh.getResponseParameter()) }
|
||||
StandardResponseSource() { this = DataFlow::parameterNode(rh.getResponseParameter()) }
|
||||
|
||||
/**
|
||||
* Gets the route handler that provides this response.
|
||||
@@ -122,13 +127,18 @@ module NodeJSLib {
|
||||
}
|
||||
|
||||
/**
|
||||
* A Node.js request source, that is, the request parameter of a
|
||||
* A Node.js request source.
|
||||
*/
|
||||
abstract class RequestSource extends HTTP::Servers::RequestSource { }
|
||||
|
||||
/**
|
||||
* A standard Node.js request source, that is, the request parameter of a
|
||||
* route handler.
|
||||
*/
|
||||
private class RequestSource extends HTTP::Servers::RequestSource {
|
||||
private class StandardRequestSource extends RequestSource {
|
||||
RouteHandler rh;
|
||||
|
||||
RequestSource() { this = DataFlow::parameterNode(rh.getRequestParameter()) }
|
||||
StandardRequestSource() { this = DataFlow::parameterNode(rh.getRequestParameter()) }
|
||||
|
||||
/**
|
||||
* Gets the route handler that handles this request.
|
||||
|
||||
@@ -103,6 +103,12 @@ nodes
|
||||
| formatting.js:7:14:7:53 | require ... , evil) |
|
||||
| formatting.js:7:14:7:53 | require ... , evil) |
|
||||
| formatting.js:7:49:7:52 | evil |
|
||||
| pages/Next.jsx:8:13:8:19 | req.url |
|
||||
| pages/Next.jsx:8:13:8:19 | req.url |
|
||||
| pages/Next.jsx:8:13:8:19 | req.url |
|
||||
| pages/Next.jsx:15:13:15:19 | req.url |
|
||||
| pages/Next.jsx:15:13:15:19 | req.url |
|
||||
| pages/Next.jsx:15:13:15:19 | req.url |
|
||||
| partial.js:9:25:9:25 | x |
|
||||
| partial.js:10:14:10:14 | x |
|
||||
| partial.js:10:14:10:18 | x + y |
|
||||
@@ -237,6 +243,8 @@ edges
|
||||
| formatting.js:6:43:6:46 | evil | formatting.js:6:14:6:47 | util.fo ... , evil) |
|
||||
| formatting.js:7:49:7:52 | evil | formatting.js:7:14:7:53 | require ... , evil) |
|
||||
| formatting.js:7:49:7:52 | evil | formatting.js:7:14:7:53 | require ... , evil) |
|
||||
| pages/Next.jsx:8:13:8:19 | req.url | pages/Next.jsx:8:13:8:19 | req.url |
|
||||
| pages/Next.jsx:15:13:15:19 | req.url | pages/Next.jsx:15:13:15:19 | req.url |
|
||||
| partial.js:9:25:9:25 | x | partial.js:10:14:10:14 | x |
|
||||
| partial.js:10:14:10:14 | x | partial.js:10:14:10:18 | x + y |
|
||||
| partial.js:10:14:10:14 | x | partial.js:10:14:10:18 | x + y |
|
||||
@@ -303,6 +311,8 @@ edges
|
||||
| etherpad.js:11:12:11:19 | response | etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:11:12:11:19 | response | Cross-site scripting vulnerability due to $@. | etherpad.js:9:16:9:30 | req.query.jsonp | user-provided value |
|
||||
| formatting.js:6:14:6:47 | util.fo ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
|
||||
| formatting.js:7:14:7:53 | require ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
|
||||
| pages/Next.jsx:8:13:8:19 | req.url | pages/Next.jsx:8:13:8:19 | req.url | pages/Next.jsx:8:13:8:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:8:13:8:19 | req.url | user-provided value |
|
||||
| pages/Next.jsx:15:13:15:19 | req.url | pages/Next.jsx:15:13:15:19 | req.url | pages/Next.jsx:15:13:15:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:15:13:15:19 | req.url | user-provided value |
|
||||
| partial.js:10:14:10:18 | x + y | partial.js:13:42:13:48 | req.url | partial.js:10:14:10:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:13:42:13:48 | req.url | user-provided value |
|
||||
| partial.js:19:14:19:18 | x + y | partial.js:22:51:22:57 | req.url | partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:51:22:57 | req.url | user-provided value |
|
||||
| partial.js:28:14:28:18 | x + y | partial.js:31:47:31:53 | req.url | partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:47:31:53 | req.url | user-provided value |
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
| ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | Cross-site scripting vulnerability due to $@. | ReflectedXssGood3.js:135:15:135:27 | req.params.id | user-provided value |
|
||||
| formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
|
||||
| formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
|
||||
| pages/Next.jsx:8:13:8:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:8:13:8:19 | req.url | user-provided value |
|
||||
| pages/Next.jsx:15:13:15:19 | req.url | Cross-site scripting vulnerability due to $@. | pages/Next.jsx:15:13:15:19 | req.url | user-provided value |
|
||||
| partial.js:10:14:10:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:13:42:13:48 | req.url | user-provided value |
|
||||
| partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:51:22:57 | req.url | user-provided value |
|
||||
| partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:47:31:53 | req.url | user-provided value |
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "^10.0.0",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
export default function Post() {
|
||||
return <span />;
|
||||
}
|
||||
|
||||
Post.getInitialProps = async (ctx) => {
|
||||
const req = ctx.req;
|
||||
const res = ctx.res;
|
||||
res.end(req.url);
|
||||
return {}
|
||||
}
|
||||
|
||||
export async function getServerSideProps(ctx) {
|
||||
const req = ctx.req;
|
||||
const res = ctx.res;
|
||||
res.end(req.url);
|
||||
return {
|
||||
props: {}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user