Add coverage for express

This commit is contained in:
Maiky
2023-10-16 16:48:32 +02:00
parent c0e6d7c049
commit 07ad596f77
5 changed files with 87 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
/**
* Provides classes for working with Cors connectors.
*/
import javascript
/** Provides classes modeling [cors package](https://npmjs.com/package/cors) */
module Cors {
class Cors extends DataFlow::CallNode {
/** Get an instanceof of `cors` */
Cors() { this = DataFlow::moduleImport("cors").getAnInvocation() }
/** Get Cors configuration */
DataFlow::Node getCorsArgument() { result = this.getArgument(0) }
/** Holds if cors is using default configuration */
predicate isDefault() { this.getNumArgument() = 0 }
/** The value of origin */
DataFlow::Node getOrigin() {
result = this.getCorsArgument().getALocalSource().getAPropertyWrite("origin").getRhs()
}
}
}

View File

@@ -5,6 +5,7 @@
import javascript import javascript
import semmle.javascript.frameworks.HTTP import semmle.javascript.frameworks.HTTP
import semmle.javascript.frameworks.ExpressModules import semmle.javascript.frameworks.ExpressModules
import semmle.javascript.frameworks.Cors
private import semmle.javascript.dataflow.InferredTypes private import semmle.javascript.dataflow.InferredTypes
private import semmle.javascript.frameworks.ConnectExpressShared::ConnectExpressShared private import semmle.javascript.frameworks.ConnectExpressShared::ConnectExpressShared
@@ -1071,4 +1072,23 @@ module Express {
override predicate definitelyResumesDispatch() { none() } override predicate definitelyResumesDispatch() { none() }
} }
class CorsConfiguration extends DataFlow::MethodCallNode {
/** Get an `app.use` with a cors object as argument */
CorsConfiguration() {
this = appCreation().getAMethodCall("use") and this.getArgument(0) instanceof Cors::Cors
}
/** Get Cors */
private Cors::Cors cors() { result = this.getArgument(0).(Cors::Cors) }
/** Get Cors configuration */
DataFlow::Node getCorsArgument() { result = cors().getCorsArgument() }
/** Holds if cors is using default configuration */
predicate isDefault() { cors().isDefault() }
/** Get Cors origin value */
DataFlow::Node getOrigin() { result = cors().getOrigin() }
}
} }

View File

@@ -44,4 +44,11 @@ module CorsPermissiveConfiguration {
) )
} }
} }
/**
* The value of cors origin when initializing the application.
*/
class ExpressCors extends Sink, DataFlow::ValueNode {
ExpressCors() { exists(Express::CorsConfiguration config | this = config.getOrigin()) }
}
} }

View File

@@ -0,0 +1,36 @@
const cors = require('cors');
var express = require('express');
var https = require('https'),
url = require('url');
var server = https.createServer(function () { });
server.on('request', function (req, res) {
let user_origin = url.parse(req.url, true).query.origin;
// BAD: CORS too permissive, default value is *
var app1 = express();
app1.use(cors());
// GOOD: restrictive CORS
var app2 = express();
var corsOptions2 = {
origin: ["https://example1.com", "https://example2.com"],
};
app2.use(cors(corsOptions2));
// BAD: CORS too permissive
var app3 = express();
var corsOption3 = {
origin: '*'
};
app3.use(cors(corsOption3));
// BAD: CORS is controlled by user
var app4 = express();
var corsOption4 = {
origin: user_origin
};
app4.use(cors(corsOption4));
});