From 8b33e6d175f67ed56998add522dbf82840482e4b Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Mon, 7 Nov 2022 16:29:44 +0100 Subject: [PATCH 01/12] Improved Hapi support - server defined by Glue --- .../lib/semmle/javascript/frameworks/Hapi.qll | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index e4bc922951cd..58cbe9b1597b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -9,10 +9,21 @@ module Hapi { /** * An expression that creates a new Hapi server. */ - class ServerDefinition extends Http::Servers::StandardServerDefinition, DataFlow::NewNode { + class ServerDefinition extends Http::Servers::StandardServerDefinition, DataFlow::Node { ServerDefinition() { // `server = new Hapi.Server()` this = DataFlow::moduleMember("hapi", "Server").getAnInstantiation() + or + // server = Glue.compose(manifest, composeOptions) + this = DataFlow::moduleMember("@hapi/glue", "compose").getAnInvocation() + or + // server inside a plugin + // TODO match `function (server, options)` + exists(Function f | + this.(DataFlow::ParameterNode).getParameter() = f.getParameter(0) and + f.getParameter(0).getName() = "server" and + f.getParameter(1).getName() = "options" + ) } } @@ -209,6 +220,16 @@ module Hapi { // server.ext('/', fun) this.getMethodName() = "ext" and handler = this.getArgument(1) + or + // server.route([{ handler(request){}]) + this.getMethodName() = "route" and + handler = + this.getArgument(0) + .(DataFlow::ArrayLiteralNode) + .getAnElement() + .(DataFlow::ObjectLiteralNode) + .getAPropertySource("handler") + .getAFunctionValue() ) } From 8e546e84968b4a963820907dee5dbe5d575d60e1 Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Tue, 8 Nov 2022 16:14:10 +0100 Subject: [PATCH 02/12] Add `req.url.origin` to `RequestInputAccess` --- javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index 58cbe9b1597b..18790d979c23 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -142,7 +142,7 @@ module Hapi { // `request.url.path` kind = "url" and url.accesses(request, "url") and - this.(DataFlow::PropRead).accesses(url, "path") + this.(DataFlow::PropRead).accesses(url, ["path", "origin"]) ) or exists(DataFlow::PropRead state | From ee02265ac2fd18bfaa8cd1eafa857fc354db7f6c Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Thu, 10 Nov 2022 12:24:39 +0100 Subject: [PATCH 03/12] Add property `params` to `RequestInputAccess` --- javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index 18790d979c23..4c7dd3e5a49a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -134,7 +134,7 @@ module Hapi { kind = "parameter" and exists(DataFlow::PropRead query | // `request.query.name` - query.accesses(request, "query") and + query.accesses(request, ["query", "params"]) and this.(DataFlow::PropRead).accesses(query, _) ) or From 5ea03b1ded4380816c8d3396a652c36841e8a856 Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Mon, 14 Nov 2022 22:56:06 +0100 Subject: [PATCH 04/12] Update Hapi.qll Add `server` definitions in plugin registration and plugin dependency declaration --- .../ql/lib/semmle/javascript/frameworks/Hapi.qll | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index 4c7dd3e5a49a..0d04aac34c63 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -14,16 +14,24 @@ module Hapi { // `server = new Hapi.Server()` this = DataFlow::moduleMember("hapi", "Server").getAnInstantiation() or - // server = Glue.compose(manifest, composeOptions) + // `server = Glue.compose(manifest, composeOptions)` this = DataFlow::moduleMember("@hapi/glue", "compose").getAnInvocation() or - // server inside a plugin - // TODO match `function (server, options)` + // `register (server, options)` exists(Function f | this.(DataFlow::ParameterNode).getParameter() = f.getParameter(0) and + f.getName() = "register" and f.getParameter(0).getName() = "server" and f.getParameter(1).getName() = "options" ) + or + // `const after = function (server) {...};` + // `server.dependency('name', after);` + exists(ServerDefinition server, DataFlow::MethodCallNode call | + call = server.ref().getAMethodCall() and + call.getMethodName() = "dependency" and + this = call.getArgument(1).(DataFlow::FunctionNode).getParameter(0) + ) } } @@ -261,7 +269,7 @@ module Hapi { RouteHandlerCandidate() { exists(string request, string responseToolkit | (request = "request" or request = "req") and - responseToolkit = "h" and + responseToolkit = ["h", "hapi"] and // heuristic: parameter names match the Hapi documentation astNode.getNumParameter() = 2 and astNode.getParameter(0).getName() = request and From 563a56af9d6781af6b1795b7d13a9c1f3f8d7528 Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Tue, 15 Nov 2022 15:46:34 +0100 Subject: [PATCH 05/12] Update Hapi.qll --- .../ql/lib/semmle/javascript/frameworks/Hapi.qll | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index 0d04aac34c63..b3bed8112ade 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -18,12 +18,14 @@ module Hapi { this = DataFlow::moduleMember("@hapi/glue", "compose").getAnInvocation() or // `register (server, options)` - exists(Function f | - this.(DataFlow::ParameterNode).getParameter() = f.getParameter(0) and - f.getName() = "register" and - f.getParameter(0).getName() = "server" and - f.getParameter(1).getName() = "options" - ) + // `module.exports.plugin = {register, pkg};` + this = + any(NodeModule m) + .getAnExportedValue("plugin") + .(DataFlow::ObjectLiteralNode) + .getAPropertySource("register") + .(DataFlow::FunctionNode) + .getParameter(0) or // `const after = function (server) {...};` // `server.dependency('name', after);` From e5e3bb3705e5272187b02cdf6b103dfb407bc910 Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Tue, 15 Nov 2022 16:27:14 +0100 Subject: [PATCH 06/12] Generalize the server definition in plugin registration --- javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index b3bed8112ade..b0b33c078dbe 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -20,11 +20,11 @@ module Hapi { // `register (server, options)` // `module.exports.plugin = {register, pkg};` this = - any(NodeModule m) + any(Module m) .getAnExportedValue("plugin") - .(DataFlow::ObjectLiteralNode) + .getALocalSource() .getAPropertySource("register") - .(DataFlow::FunctionNode) + .getAFunctionValue() .getParameter(0) or // `const after = function (server) {...};` From 8109a7b67a6cdb654e03d9ada70d235319cb4e70 Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Tue, 15 Nov 2022 16:27:21 +0100 Subject: [PATCH 07/12] Update javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll Co-authored-by: Erik Krogh Kristensen --- javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index b0b33c078dbe..c791cd9e25dc 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -32,7 +32,7 @@ module Hapi { exists(ServerDefinition server, DataFlow::MethodCallNode call | call = server.ref().getAMethodCall() and call.getMethodName() = "dependency" and - this = call.getArgument(1).(DataFlow::FunctionNode).getParameter(0) + this = call.getABoundCallbackParameter(1, 0) ) } } From ec04f0c88f79482386bcef2ddda2613e2ede860f Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Tue, 15 Nov 2022 23:45:27 +0100 Subject: [PATCH 08/12] hapi/glue tests --- .../frameworks/hapi/src/hapiglue.js | 50 +++++++++++++ .../frameworks/hapi/tests.expected | 70 +++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 javascript/ql/test/library-tests/frameworks/hapi/src/hapiglue.js diff --git a/javascript/ql/test/library-tests/frameworks/hapi/src/hapiglue.js b/javascript/ql/test/library-tests/frameworks/hapi/src/hapiglue.js new file mode 100644 index 000000000000..d2401209028f --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/hapi/src/hapiglue.js @@ -0,0 +1,50 @@ +var server1 = new (require('@hapi/glue')).compose(require("./manifest"), composeOptions); // test_ServerDefinition + +var Hapi = require('@hapi/glue'); +var server2 = new Hapi.compose(require("./manifest"), composeOptions); // test_ServerDefinition + +function handler1(){} // HTTP::RouteHandler +server2.route({ + handler: handler1 +}); + + +server2.route({ + handler: function handler2(request, reply){ // HTTP::RouteHandler + request.response.header('HEADER1', '') // HTTP::HeaderDefinition + }}); + +server2.ext('onPreResponse', function handler3(request, reply) { // HTTP::RouteHandler +}) + +function handler4(request, reply){ + request.rawPayload; + request.payload.foo; + request.query.bar; + request.params.bar; + request.url.path; + request.url.origin; + request.headers.baz; + request.state.token; +} +var route = {handler: handler4}; +server2.route(route); + +server2.cache({ segment: 'countries', expiresIn: 60*60*1000 }); + +function getHandler() { + return function (req, hapi){} +} +server2.route({handler: getHandler()}); + +function after(server) { +}; + +function register(server, options) {// test_ServerDefinition + server.dependency(options.dependencies, server_ => after(server_, options)); // test_ServerDefinition +} + +module.exports.plugin = { + register, + pkg +}; diff --git a/javascript/ql/test/library-tests/frameworks/hapi/tests.expected b/javascript/ql/test/library-tests/frameworks/hapi/tests.expected index fb73a32acf62..57d3d4a81f7e 100644 --- a/javascript/ql/test/library-tests/frameworks/hapi/tests.expected +++ b/javascript/ql/test/library-tests/frameworks/hapi/tests.expected @@ -4,6 +4,11 @@ test_RouteSetup | src/hapi.js:17:1:18:2 | server2 ... dler\\n}) | | src/hapi.js:29:1:29:20 | server2.route(route) | | src/hapi.js:36:1:36:38 | server2 ... ler()}) | +| src/hapiglue.js:7:1:9:2 | server2 ... ler1\\n}) | +| src/hapiglue.js:12:1:15:7 | server2 ... }}) | +| src/hapiglue.js:17:1:18:2 | server2 ... dler\\n}) | +| src/hapiglue.js:31:1:31:20 | server2.route(route) | +| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | test_RequestInputAccess | src/hapi.js:21:3:21:20 | request.rawPayload | body | src/hapi.js:20:1:27:1 | functio ... oken;\\n} | | src/hapi.js:22:3:22:21 | request.payload.foo | body | src/hapi.js:20:1:27:1 | functio ... oken;\\n} | @@ -11,27 +16,50 @@ test_RequestInputAccess | src/hapi.js:24:3:24:18 | request.url.path | url | src/hapi.js:20:1:27:1 | functio ... oken;\\n} | | src/hapi.js:25:3:25:21 | request.headers.baz | header | src/hapi.js:20:1:27:1 | functio ... oken;\\n} | | src/hapi.js:26:3:26:21 | request.state.token | cookie | src/hapi.js:20:1:27:1 | functio ... oken;\\n} | +| src/hapiglue.js:21:3:21:20 | request.rawPayload | body | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:22:3:22:21 | request.payload.foo | body | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:23:3:23:19 | request.query.bar | parameter | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:24:3:24:20 | request.params.bar | parameter | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:25:3:25:18 | request.url.path | url | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:26:3:26:20 | request.url.origin | url | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:27:3:27:21 | request.headers.baz | header | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:28:3:28:21 | request.state.token | cookie | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | test_RouteHandler_getAResponseHeader | src/hapi.js:13:14:15:5 | functio ... n\\n } | header1 | src/hapi.js:14:9:14:46 | request ... 1', '') | +| src/hapiglue.js:13:14:15:5 | functio ... n\\n } | header1 | src/hapiglue.js:14:9:14:46 | request ... 1', '') | test_HeaderDefinition_defines | src/hapi.js:14:9:14:46 | request ... 1', '') | header1 | | +| src/hapiglue.js:14:9:14:46 | request ... 1', '') | header1 | | test_ResponseExpr | src/hapi.js:14:9:14:24 | request.response | src/hapi.js:13:14:15:5 | functio ... n\\n } | +| src/hapiglue.js:14:9:14:24 | request.response | src/hapiglue.js:13:14:15:5 | functio ... n\\n } | test_HeaderDefinition | src/hapi.js:14:9:14:46 | request ... 1', '') | src/hapi.js:13:14:15:5 | functio ... n\\n } | +| src/hapiglue.js:14:9:14:46 | request ... 1', '') | src/hapiglue.js:13:14:15:5 | functio ... n\\n } | test_RouteSetup_getServer | src/hapi.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapi.js:4:15:4:31 | new Hapi.Server() | | src/hapi.js:12:1:15:7 | server2 ... }}) | src/hapi.js:4:15:4:31 | new Hapi.Server() | | src/hapi.js:17:1:18:2 | server2 ... dler\\n}) | src/hapi.js:4:15:4:31 | new Hapi.Server() | | src/hapi.js:29:1:29:20 | server2.route(route) | src/hapi.js:4:15:4:31 | new Hapi.Server() | | src/hapi.js:36:1:36:38 | server2 ... ler()}) | src/hapi.js:4:15:4:31 | new Hapi.Server() | +| src/hapiglue.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) | +| src/hapiglue.js:12:1:15:7 | server2 ... }}) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) | +| src/hapiglue.js:17:1:18:2 | server2 ... dler\\n}) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) | +| src/hapiglue.js:31:1:31:20 | server2.route(route) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) | +| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) | test_HeaderDefinition_getAHeaderName | src/hapi.js:14:9:14:46 | request ... 1', '') | header1 | +| src/hapiglue.js:14:9:14:46 | request ... 1', '') | header1 | test_ServerDefinition | src/hapi.js:1:15:1:44 | new (re ... erver() | | src/hapi.js:4:15:4:31 | new Hapi.Server() | +| src/hapiglue.js:1:15:1:88 | new (re ... ptions) | +| src/hapiglue.js:4:15:4:69 | new Hap ... ptions) | +| src/hapiglue.js:43:19:43:24 | server | +| src/hapiglue.js:44:45:44:51 | server_ | test_HeaderAccess | src/hapi.js:25:3:25:21 | request.headers.baz | baz | +| src/hapiglue.js:27:3:27:21 | request.headers.baz | baz | test_RouteSetup_getARouteHandler | src/hapi.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapi.js:6:1:6:21 | functio ... er1(){} | | src/hapi.js:12:1:15:7 | server2 ... }}) | src/hapi.js:13:14:15:5 | functio ... n\\n } | @@ -40,12 +68,24 @@ test_RouteSetup_getARouteHandler | src/hapi.js:36:1:36:38 | server2 ... ler()}) | src/hapi.js:33:1:35:1 | return of function getHandler | | src/hapi.js:36:1:36:38 | server2 ... ler()}) | src/hapi.js:34:12:34:30 | function (req, h){} | | src/hapi.js:36:1:36:38 | server2 ... ler()}) | src/hapi.js:36:25:36:36 | getHandler() | +| src/hapiglue.js:7:1:9:2 | server2 ... ler1\\n}) | src/hapiglue.js:6:1:6:21 | functio ... er1(){} | +| src/hapiglue.js:12:1:15:7 | server2 ... }}) | src/hapiglue.js:13:14:15:5 | functio ... n\\n } | +| src/hapiglue.js:17:1:18:2 | server2 ... dler\\n}) | src/hapiglue.js:17:30:18:1 | functio ... ndler\\n} | +| src/hapiglue.js:31:1:31:20 | server2.route(route) | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:35:1:37:1 | return of function getHandler | +| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:36:12:36:33 | functio ... hapi){} | +| src/hapiglue.js:38:1:38:38 | server2 ... ler()}) | src/hapiglue.js:38:25:38:36 | getHandler() | test_RouteHandler | src/hapi.js:6:1:6:21 | functio ... er1(){} | src/hapi.js:4:15:4:31 | new Hapi.Server() | | src/hapi.js:13:14:15:5 | functio ... n\\n } | src/hapi.js:4:15:4:31 | new Hapi.Server() | | src/hapi.js:17:30:18:1 | functio ... ndler\\n} | src/hapi.js:4:15:4:31 | new Hapi.Server() | | src/hapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapi.js:4:15:4:31 | new Hapi.Server() | | src/hapi.js:34:12:34:30 | function (req, h){} | src/hapi.js:4:15:4:31 | new Hapi.Server() | +| src/hapiglue.js:6:1:6:21 | functio ... er1(){} | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) | +| src/hapiglue.js:13:14:15:5 | functio ... n\\n } | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) | +| src/hapiglue.js:17:30:18:1 | functio ... ndler\\n} | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) | +| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) | +| src/hapiglue.js:36:12:36:33 | functio ... hapi){} | src/hapiglue.js:4:15:4:69 | new Hap ... ptions) | test_RequestExpr | src/hapi.js:13:32:13:38 | request | src/hapi.js:13:14:15:5 | functio ... n\\n } | | src/hapi.js:13:32:13:38 | request | src/hapi.js:13:14:15:5 | functio ... n\\n } | @@ -60,6 +100,21 @@ test_RequestExpr | src/hapi.js:25:3:25:9 | request | src/hapi.js:20:1:27:1 | functio ... oken;\\n} | | src/hapi.js:26:3:26:9 | request | src/hapi.js:20:1:27:1 | functio ... oken;\\n} | | src/hapi.js:34:22:34:24 | req | src/hapi.js:34:12:34:30 | function (req, h){} | +| src/hapiglue.js:13:32:13:38 | request | src/hapiglue.js:13:14:15:5 | functio ... n\\n } | +| src/hapiglue.js:13:32:13:38 | request | src/hapiglue.js:13:14:15:5 | functio ... n\\n } | +| src/hapiglue.js:14:9:14:15 | request | src/hapiglue.js:13:14:15:5 | functio ... n\\n } | +| src/hapiglue.js:17:48:17:54 | request | src/hapiglue.js:17:30:18:1 | functio ... ndler\\n} | +| src/hapiglue.js:20:19:20:25 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:20:19:20:25 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:21:3:21:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:22:3:22:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:23:3:23:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:24:3:24:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:25:3:25:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:26:3:26:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:27:3:27:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:28:3:28:9 | request | src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | +| src/hapiglue.js:36:22:36:24 | req | src/hapiglue.js:36:12:36:33 | functio ... hapi){} | test_RouteHandler_getARequestExpr | src/hapi.js:13:14:15:5 | functio ... n\\n } | src/hapi.js:13:32:13:38 | request | | src/hapi.js:13:14:15:5 | functio ... n\\n } | src/hapi.js:13:32:13:38 | request | @@ -74,3 +129,18 @@ test_RouteHandler_getARequestExpr | src/hapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapi.js:25:3:25:9 | request | | src/hapi.js:20:1:27:1 | functio ... oken;\\n} | src/hapi.js:26:3:26:9 | request | | src/hapi.js:34:12:34:30 | function (req, h){} | src/hapi.js:34:22:34:24 | req | +| src/hapiglue.js:13:14:15:5 | functio ... n\\n } | src/hapiglue.js:13:32:13:38 | request | +| src/hapiglue.js:13:14:15:5 | functio ... n\\n } | src/hapiglue.js:13:32:13:38 | request | +| src/hapiglue.js:13:14:15:5 | functio ... n\\n } | src/hapiglue.js:14:9:14:15 | request | +| src/hapiglue.js:17:30:18:1 | functio ... ndler\\n} | src/hapiglue.js:17:48:17:54 | request | +| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:20:19:20:25 | request | +| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:20:19:20:25 | request | +| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:21:3:21:9 | request | +| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:22:3:22:9 | request | +| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:23:3:23:9 | request | +| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:24:3:24:9 | request | +| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:25:3:25:9 | request | +| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:26:3:26:9 | request | +| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:27:3:27:9 | request | +| src/hapiglue.js:20:1:29:1 | functio ... oken;\\n} | src/hapiglue.js:28:3:28:9 | request | +| src/hapiglue.js:36:12:36:33 | functio ... hapi){} | src/hapiglue.js:36:22:36:24 | req | From 84cb59b942da4d402c30450820f71a6ccc79874e Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Wed, 16 Nov 2022 11:05:23 +0100 Subject: [PATCH 09/12] Create 2022-11-08-hapi-glue.md --- javascript/ql/src/change-notes/2022-11-08-hapi-glue.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 javascript/ql/src/change-notes/2022-11-08-hapi-glue.md diff --git a/javascript/ql/src/change-notes/2022-11-08-hapi-glue.md b/javascript/ql/src/change-notes/2022-11-08-hapi-glue.md new file mode 100644 index 000000000000..18816a2af138 --- /dev/null +++ b/javascript/ql/src/change-notes/2022-11-08-hapi-glue.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added support for @hapi/glue and Hapi plugins to the frameworks/Hapi.qll library. From 798b03f29dca3c4616a916068238c71a8d8e2ee9 Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Wed, 16 Nov 2022 12:06:07 +0100 Subject: [PATCH 10/12] code generalization Co-authored-by: Erik Krogh Kristensen --- javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index c791cd9e25dc..150096a1bcff 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -235,7 +235,8 @@ module Hapi { this.getMethodName() = "route" and handler = this.getArgument(0) - .(DataFlow::ArrayLiteralNode) + .getALocalSource() + .(DataFlow::ArrayCreationNode) .getAnElement() .(DataFlow::ObjectLiteralNode) .getAPropertySource("handler") From 8bf0bbb715526d388e3b3909201cc3f493eca20f Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Wed, 16 Nov 2022 12:06:23 +0100 Subject: [PATCH 11/12] code generalization Co-authored-by: Erik Krogh Kristensen --- javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index 150096a1bcff..46bbb624839d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -238,7 +238,7 @@ module Hapi { .getALocalSource() .(DataFlow::ArrayCreationNode) .getAnElement() - .(DataFlow::ObjectLiteralNode) + .getALocalSource() .getAPropertySource("handler") .getAFunctionValue() ) From 49f476d3b4f3bd22a11eecbc131a1b77bd2b9034 Mon Sep 17 00:00:00 2001 From: Mauro Baluda Date: Wed, 16 Nov 2022 23:53:07 +0100 Subject: [PATCH 12/12] Update javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll Co-authored-by: Erik Krogh Kristensen --- javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index 46bbb624839d..f38740a490da 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -29,11 +29,8 @@ module Hapi { or // `const after = function (server) {...};` // `server.dependency('name', after);` - exists(ServerDefinition server, DataFlow::MethodCallNode call | - call = server.ref().getAMethodCall() and - call.getMethodName() = "dependency" and - this = call.getABoundCallbackParameter(1, 0) - ) + this = + any(ServerDefinition s).ref().getAMethodCall("dependency").getABoundCallbackParameter(1, 0) } }