mirror of
https://github.com/github/codeql.git
synced 2026-05-01 11:45:14 +02:00
add parameter values from Next as a RemoteFlowSource
This commit is contained in:
@@ -96,6 +96,7 @@ import semmle.javascript.frameworks.Logging
|
||||
import semmle.javascript.frameworks.HttpFrameworks
|
||||
import semmle.javascript.frameworks.HttpProxy
|
||||
import semmle.javascript.frameworks.Markdown
|
||||
import semmle.javascript.frameworks.Next
|
||||
import semmle.javascript.frameworks.NoSQL
|
||||
import semmle.javascript.frameworks.PkgCloud
|
||||
import semmle.javascript.frameworks.PropertyProjection
|
||||
|
||||
56
javascript/ql/src/semmle/javascript/frameworks/Next.qll
Normal file
56
javascript/ql/src/semmle/javascript/frameworks/Next.qll
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Provides classes and predicates for reasoning about [Next.js](https://www.npmjs.com/package/next).
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* Provides classes and predicates modelling [Next.js](https://www.npmjs.com/package/next).
|
||||
*/
|
||||
private module NextJS {
|
||||
/**
|
||||
* Gets a `package.json` that depends on the `Next.js` library.
|
||||
*/
|
||||
PackageJSON getANextPackage() { result.getDependencies().getADependency("next", _) }
|
||||
|
||||
/**
|
||||
* Gets a "pages" folder in a `Next.js` application.
|
||||
* JavaScript files inside these folders are mapped to routes.
|
||||
*/
|
||||
Folder getAPagesFolder() {
|
||||
result = getANextPackage().getFile().getParentContainer().getFolder("pages")
|
||||
or
|
||||
result = getAPagesFolder().getAFolder()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a module inside a "pages" folder where `fallback` from `getStaticPaths` is not set to false.
|
||||
* In such a module the `getStaticProps` method can be called with user-defined parameters.
|
||||
* If `fallback` is set to false, then only values defined by `getStaticPaths` are allowed.
|
||||
*/
|
||||
Module getAModuleWithFallbackPaths() {
|
||||
result.getFile().getParentContainer() = getAPagesFolder() and
|
||||
exists(DataFlow::FunctionNode staticPaths, Expr fallback |
|
||||
staticPaths = result.getAnExportedValue("getStaticPaths").getAFunctionValue() and
|
||||
fallback =
|
||||
staticPaths.getAReturn().getALocalSource().getAPropertyWrite("fallback").getRhs().asExpr() and
|
||||
not fallback.(BooleanLiteral).getValue() = "false"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* User defined path parameter in `Next.js`.
|
||||
*/
|
||||
class NextParams extends RemoteFlowSource {
|
||||
NextParams() {
|
||||
this =
|
||||
getAModuleWithFallbackPaths()
|
||||
.getAnExportedValue("getStaticProps")
|
||||
.getAFunctionValue()
|
||||
.getParameter(0)
|
||||
.getAPropertyRead("params")
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "Next request parameter" }
|
||||
}
|
||||
}
|
||||
@@ -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,21 @@
|
||||
export async function getStaticPaths() {
|
||||
return {
|
||||
paths: [],
|
||||
fallback: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function getStaticProps({ params }) {
|
||||
return {
|
||||
props: {
|
||||
id: params.id,
|
||||
taint: source()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default function Post({ taint }) {
|
||||
sink(taint);
|
||||
return <span />;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
remoteFlow
|
||||
| pages/[my-fallback-id].jsx:9:40:9:45 | params |
|
||||
dataFlow
|
||||
19
javascript/ql/test/library-tests/frameworks/Next/tests.ql
Normal file
19
javascript/ql/test/library-tests/frameworks/Next/tests.ql
Normal file
@@ -0,0 +1,19 @@
|
||||
import javascript
|
||||
|
||||
query RemoteFlowSource remoteFlow() { any() }
|
||||
|
||||
class Config extends DataFlow::Configuration {
|
||||
Config() { this = "Config" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.(DataFlow::CallNode).getCalleeName() = "source"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(DataFlow::CallNode call | call.getCalleeName() = "sink" | call.getAnArgument() = sink)
|
||||
}
|
||||
}
|
||||
|
||||
query predicate dataFlow(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(Config c).hasFlow(pred, succ)
|
||||
}
|
||||
Reference in New Issue
Block a user