import javascript import semmle.javascript.security.dataflow.ReflectedXss::ReflectedXss /** * A function with `req` and `res` parameters, and hence most likely an * HTTP route handler. */ class LikelyRouteHandler extends DataFlow::FunctionNode { DataFlow::ParameterNode req; DataFlow::ParameterNode res; LikelyRouteHandler() { req = getParameter(0) and req.getName() = "req" and res = getParameter(1) and res.getName() = "res" } DataFlow::ParameterNode getRequestParameter() { result = req } /** Gets a method of `res` that sends an HTTP response. */ string getASendMethodName() { // res.send result = "send" or // or a method `m` such that there is an assignment `res.m = res.n` where `n` // is already known to be a send method exists (DataFlow::PropWrite pwn | pwn = res.getAPropertyWrite(result) and pwn.getRhs() = getASendMethodReference() ) } /** Gets a reference to `res.send` or some other known send method. */ DataFlow::PropRead getASendMethodReference() { result = res.getAPropertyRead(getASendMethodName()) } /** Gets a call to the send method. */ DataFlow::CallNode getASendMethodCall() { result = getASendMethodReference().getACall() } } /** An argument passed to `res.send`, marked as an XSS sink. */ class LikelySendArgument extends Sink { LikelySendArgument() { this = any(LikelyRouteHandler rh).getASendMethodCall().getAnArgument() } } /** An access to a request parameter, marked as an XSS source. */ class LikelyRequestParameter extends Source, DataFlow::SourceNode { LikelyRequestParameter() { exists (DataFlow::SourceNode base | this = base.getAPropertyRead() | // either a property access on `req` itself base = any(LikelyRouteHandler rh).getRequestParameter() or // or a more deeply nested property access base instanceof LikelyRequestParameter ) } } // We will treat the parameters of the route handler functions as the // sources in our data flow analysis. from LikelyRequestParameter p select p