mirror of
https://github.com/github/codeql.git
synced 2025-12-22 11:46:32 +01:00
Add coverage for express
This commit is contained in:
24
javascript/ql/lib/semmle/javascript/frameworks/Cors.qll
Normal file
24
javascript/ql/lib/semmle/javascript/frameworks/Cors.qll
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user