mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
add a RemoteFlowSource for serverless handlers
This commit is contained in:
@@ -94,6 +94,7 @@ import semmle.javascript.frameworks.PropertyProjection
|
||||
import semmle.javascript.frameworks.React
|
||||
import semmle.javascript.frameworks.ReactNative
|
||||
import semmle.javascript.frameworks.Request
|
||||
import semmle.javascript.frameworks.ServerLess
|
||||
import semmle.javascript.frameworks.ShellJS
|
||||
import semmle.javascript.frameworks.SystemCommandExecutors
|
||||
import semmle.javascript.frameworks.SQL
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Provides classes and predicates for working with serverless handlers.
|
||||
* E.g. AWS: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html
|
||||
*/
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.PackageExports as Exports
|
||||
|
||||
/**
|
||||
* Provides classes and predicates for working with serverless handlers.
|
||||
*/
|
||||
private module ServerLess {
|
||||
/**
|
||||
* Holds if the `.yml` file `ymlFile` contains a serverless configuration with `handler` and `codeURI` properties.
|
||||
* `codeURI` defaults to the empty string if no explicit value is set in the configuration.
|
||||
*/
|
||||
private predicate hasServerlessHandler(File ymlFile, string handler, string codeURI) {
|
||||
exists(YAMLMapping resource | ymlFile = resource.getFile() |
|
||||
// There exists at least "AWS::Serverless::Function" and "Aliyun::Serverless::Function"
|
||||
resource.lookup("Type").(YAMLScalar).getValue().regexpMatch(".*::Serverless::Function") and
|
||||
exists(YAMLMapping properties | properties = resource.lookup("Properties") |
|
||||
handler = properties.lookup("Handler").(YAMLScalar).getValue() and
|
||||
if exists(properties.lookup("CodeUri"))
|
||||
then codeURI = properties.lookup("CodeUri").(YAMLScalar).getValue()
|
||||
else codeURI = ""
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string where an ending "/." is simplified to "/" (if it exists).
|
||||
*/
|
||||
bindingset[base]
|
||||
private string removeTrailingDot(string base) {
|
||||
if base.regexpMatch(".*/\\.")
|
||||
then result = base.substring(0, base.length() - 1)
|
||||
else result = base
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string where a leading "./" is simplified to "" (if it exists).
|
||||
*/
|
||||
bindingset[base]
|
||||
private string removeLeadingDotSlash(string base) {
|
||||
if base.regexpMatch("\\./.*") then result = base.substring(2, base.length()) else result = base
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a path to a file from a `codeURI` property and a file name from a serverless configuration.
|
||||
*/
|
||||
bindingset[codeURI, file]
|
||||
private string getPathFromHandlerProperties(string codeURI, string file) {
|
||||
exists(string folder | folder = removeLeadingDotSlash(removeTrailingDot(codeURI)) |
|
||||
if folder.regexpMatch(".*\\..+") then result = folder else result = folder + file + ".js"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `file` has a serverless handler function with name `func`.
|
||||
*/
|
||||
private predicate hasServerlessHandler(File file, string func) {
|
||||
exists(File ymlFile, string handler, string codeURI, string fileName |
|
||||
hasServerlessHandler(ymlFile, handler, codeURI) and
|
||||
func = handler.regexpCapture(".*\\.(.*)", 1) and
|
||||
fileName = handler.regexpCapture("([^.]+).*", 1)
|
||||
|
|
||||
file.getAbsolutePath() =
|
||||
ymlFile.getParentContainer().getAbsolutePath() + "/" +
|
||||
getPathFromHandlerProperties(codeURI, fileName)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a function that is a serverless request handler.
|
||||
*/
|
||||
private DataFlow::FunctionNode getAServerlessHandler() {
|
||||
exists(File file, string handler, Module mod | hasServerlessHandler(file, handler) |
|
||||
mod.getFile() = file and
|
||||
result = mod.getAnExportedValue(handler).getAFunctionValue()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A serverless request handler event, seen as a RemoteFlowSource.
|
||||
*/
|
||||
private class ServerlessHandlerEventAsRemoteFlow extends RemoteFlowSource {
|
||||
ServerlessHandlerEventAsRemoteFlow() { this = getAServerlessHandler().getParameter(0) }
|
||||
|
||||
override string getSourceType() { result = "Serverless event" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
| tst1/backend/src/mylibrary.js:1:36:1:40 | event |
|
||||
| tst2/nodejs/index.js:1:36:1:40 | event |
|
||||
| tst3/function/index.js:1:36:1:40 | event |
|
||||
| tst4/app.js:1:36:1:40 | event |
|
||||
| tst5/app.js:1:36:1:40 | event |
|
||||
@@ -0,0 +1,3 @@
|
||||
import javascript
|
||||
|
||||
query RemoteFlowSource remoteFlow() { any() }
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports.handler = function (event) {
|
||||
console.log(event);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Transform: 'AWS::Serverless-2016-10-31'
|
||||
Description: 'Serverless thing'
|
||||
|
||||
Globals:
|
||||
Api:
|
||||
Cors:
|
||||
AllowMethods: "'*'"
|
||||
AllowHeaders: "'*'"
|
||||
AllowOrigin: "'*'"
|
||||
|
||||
Resources:
|
||||
OrderManagerJsFunction:
|
||||
Type: 'AWS::Serverless::Function'
|
||||
Properties:
|
||||
FunctionName: MY-SERVERLESS-THING
|
||||
Handler: mylibrary.handler
|
||||
Runtime: nodejs12.x
|
||||
CodeUri: backend/src/
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports.handler = function (event) {
|
||||
console.log(event);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
Transform: 'Aliyun::Serverless-2018-04-03'
|
||||
Resources:
|
||||
fc-mongo:
|
||||
Type: 'Aliyun::Serverless::Service'
|
||||
Properties:
|
||||
Description: MyServiceThing
|
||||
nodejs:
|
||||
Type: 'Aliyun::Serverless::Function'
|
||||
Properties:
|
||||
Handler: index.handler
|
||||
Runtime: nodejs10
|
||||
CodeUri: nodejs/
|
||||
python:
|
||||
Type: 'Aliyun::Serverless::Function'
|
||||
Properties:
|
||||
Handler: 'index.handler'
|
||||
Runtime: python3
|
||||
CodeUri: python/
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports.handler = function (event) {
|
||||
console.log(event);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Transform: 'AWS::Serverless-2016-10-31'
|
||||
Description: An AWS Lambda application.
|
||||
Resources:
|
||||
function:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Handler: index.handler
|
||||
Runtime: nodejs12.x
|
||||
CodeUri: function/.
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports.handler = function (event) {
|
||||
console.log(event);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Transform: 'AWS::Serverless-2016-10-31'
|
||||
Description: A AWS Lambda function.
|
||||
|
||||
Resources:
|
||||
helloworld:
|
||||
Type: 'AWS::Serverless::Function'
|
||||
Properties:
|
||||
Handler: app.handler
|
||||
Runtime: nodejs6.10
|
||||
CodeUri: ./
|
||||
Description: A AWS Lambda function.
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports.handler = function (event) {
|
||||
console.log(event);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
AWSTemplateFormatVersion: '2010-09-09'
|
||||
Transform: 'AWS::Serverless-2016-10-31'
|
||||
Description: A AWS Lambda function.
|
||||
|
||||
Resources:
|
||||
helloworld:
|
||||
Type: 'AWS::Serverless::Function'
|
||||
Properties:
|
||||
Handler: app.handler
|
||||
Runtime: nodejs6.10
|
||||
Description: A AWS Lambda function.
|
||||
Reference in New Issue
Block a user