mirror of
https://github.com/github/codeql.git
synced 2026-04-28 02:05:14 +02:00
Merge pull request #992 from xiemaisi/js/socket.io
Approved by asger-semmle
This commit is contained in:
@@ -79,6 +79,7 @@ import semmle.javascript.frameworks.React
|
||||
import semmle.javascript.frameworks.ReactNative
|
||||
import semmle.javascript.frameworks.Request
|
||||
import semmle.javascript.frameworks.SQL
|
||||
import semmle.javascript.frameworks.SocketIO
|
||||
import semmle.javascript.frameworks.StringFormatters
|
||||
import semmle.javascript.frameworks.UriLibraries
|
||||
import semmle.javascript.frameworks.Vue
|
||||
|
||||
239
javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll
Normal file
239
javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll
Normal file
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* Provides classes for working with [socket.io](https://socket.io).
|
||||
*/
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
|
||||
/**
|
||||
* Provides classes for working with server-side socket.io code.
|
||||
*
|
||||
* We model three concepts: servers, namespaces, and sockets. A server
|
||||
* has one or more namespaces associated with it, each identified by
|
||||
* a path name. There is always a default namespace associated with the
|
||||
* path "/". Data flows between client and server side through sockets,
|
||||
* with each socket belonging to a namespace on a server.
|
||||
*/
|
||||
module SocketIO {
|
||||
/** Gets the name of a method on `EventEmitter` that returns `this`. */
|
||||
private string chainableEventEmitterMethod() {
|
||||
result = "off" or
|
||||
result = "on" or
|
||||
result = "once" or
|
||||
result = "prependListener" or
|
||||
result = "prependOnceListener" or
|
||||
result = "removeAllListeners" or
|
||||
result = "removeListener" or
|
||||
result = "setMaxListeners"
|
||||
}
|
||||
|
||||
/** A data flow node that may produce (that is, create or return) a socket.io server. */
|
||||
class ServerNode extends DataFlow::SourceNode {
|
||||
ServerNode() {
|
||||
// server creation
|
||||
this = DataFlow::moduleImport("socket.io").getAnInvocation()
|
||||
or
|
||||
// alias for `Server`
|
||||
this = DataFlow::moduleImport("socket.io").getAMemberCall("listen")
|
||||
or
|
||||
// invocation of a chainable method
|
||||
exists(DataFlow::MethodCallNode mcn, string m |
|
||||
m = "adapter" or
|
||||
m = "attach" or
|
||||
m = "bind" or
|
||||
m = "listen" or
|
||||
m = "onconnection" or
|
||||
m = "origins" or
|
||||
m = "path" or
|
||||
m = "serveClient" or
|
||||
m = "set"
|
||||
|
|
||||
mcn = any(ServerNode srv).getAMethodCall(m) and
|
||||
// exclude getter versions
|
||||
not mcn.getNumArgument() = 0 and
|
||||
this = mcn
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A data flow node that may produce a namespace object. */
|
||||
class NamespaceNode extends DataFlow::SourceNode {
|
||||
NamespaceNode() {
|
||||
// namespace lookup
|
||||
exists(ServerNode srv |
|
||||
this = srv.getAPropertyRead("sockets")
|
||||
or
|
||||
this = srv.getAMethodCall("of")
|
||||
)
|
||||
or
|
||||
// invocation of a chainable method
|
||||
exists(string m |
|
||||
m = "binary" or
|
||||
m = "clients" or
|
||||
m = "compress" or
|
||||
m = "emit" or
|
||||
m = "in" or
|
||||
m = "send" or
|
||||
m = "to" or
|
||||
m = "use" or
|
||||
m = "write" or
|
||||
m = chainableEventEmitterMethod()
|
||||
|
|
||||
this = any(NamespaceNode ns).getAMethodCall(m)
|
||||
or
|
||||
// server objects forward these methods to their default namespace
|
||||
this = any(ServerNode srv).getAMethodCall(m)
|
||||
)
|
||||
or
|
||||
// invocation of chainable getter method
|
||||
exists(string m |
|
||||
m = "json" or
|
||||
m = "local" or
|
||||
m = "volatile"
|
||||
|
|
||||
this = any(NamespaceNode base).getAPropertyRead(m)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A data flow node that may produce a socket object. */
|
||||
class SocketNode extends DataFlow::SourceNode {
|
||||
SocketNode() {
|
||||
// callback accepting a socket
|
||||
exists(DataFlow::SourceNode base, string connect, DataFlow::MethodCallNode on |
|
||||
(base instanceof ServerNode or base instanceof NamespaceNode) and
|
||||
(connect = "connect" or connect = "connection")
|
||||
|
|
||||
on = base.getAMethodCall("on") and
|
||||
on.getArgument(0).mayHaveStringValue(connect) and
|
||||
this = on.getCallback(1).getParameter(0)
|
||||
)
|
||||
or
|
||||
// invocation of a chainable method
|
||||
exists(string m |
|
||||
m = "binary" or
|
||||
m = "compress" or
|
||||
m = "disconnect" or
|
||||
m = "emit" or
|
||||
m = "in" or
|
||||
m = "join" or
|
||||
m = "leave" or
|
||||
m = "send" or
|
||||
m = "to" or
|
||||
m = "use" or
|
||||
m = "write" or
|
||||
m = chainableEventEmitterMethod()
|
||||
|
|
||||
this = any(SocketNode base).getAMethodCall(m)
|
||||
)
|
||||
or
|
||||
// invocation of a chainable getter method
|
||||
exists(string m |
|
||||
m = "broadcast" or
|
||||
m = "json" or
|
||||
m = "local" or
|
||||
m = "volatile"
|
||||
|
|
||||
this = any(SocketNode base).getAPropertyRead(m)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node representing an API call that receives data from a client.
|
||||
*/
|
||||
class ReceiveNode extends DataFlow::MethodCallNode {
|
||||
SocketNode socket;
|
||||
|
||||
DataFlow::Node eventName;
|
||||
|
||||
ReceiveNode() {
|
||||
exists(string on |
|
||||
on = "addListener" or
|
||||
on = "on" or
|
||||
on = "once" or
|
||||
on = "prependListener" or
|
||||
on = "prependOnceListener"
|
||||
|
|
||||
this = socket.getAMethodCall(on) and
|
||||
eventName = getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the socket through which data is received. */
|
||||
SocketNode getSocket() { result = socket }
|
||||
|
||||
/** Gets the event name associated with the data, if it can be determined. */
|
||||
string getEventName() { eventName.mayHaveStringValue(result) }
|
||||
|
||||
/** Gets a data flow node representing data received from a client. */
|
||||
DataFlow::SourceNode getAReceivedItem() { result = getCallback(1).getAParameter() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node representing data received from a client, viewed as remote user input.
|
||||
*/
|
||||
private class ReceivedItemAsRemoteFlow extends RemoteFlowSource {
|
||||
ReceivedItemAsRemoteFlow() { this = any(ReceiveNode rercv).getAReceivedItem() }
|
||||
|
||||
override string getSourceType() { result = "socket.io client data" }
|
||||
|
||||
override predicate isUserControlledObject() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node representing an API call that sends data to a client.
|
||||
*/
|
||||
class SendNode extends DataFlow::MethodCallNode {
|
||||
DataFlow::SourceNode base;
|
||||
|
||||
int firstDataIndex;
|
||||
|
||||
SendNode() {
|
||||
exists(string m |
|
||||
(base instanceof ServerNode or base instanceof NamespaceNode or base instanceof SocketNode) and
|
||||
this = base.getAMethodCall(m)
|
||||
|
|
||||
// a call to `emit`
|
||||
m = "emit" and
|
||||
firstDataIndex = 1
|
||||
or
|
||||
// a call to `send` or `write`
|
||||
(m = "send" or m = "write") and
|
||||
firstDataIndex = 0
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the socket through which data is sent to the client.
|
||||
*
|
||||
* This predicate is not defined for broadcasting sends.
|
||||
*/
|
||||
SocketNode getSocket() { result = base }
|
||||
|
||||
/** Gets the event name associated with the data, if it can be determined. */
|
||||
string getEventName() {
|
||||
if firstDataIndex = 1 then getArgument(0).mayHaveStringValue(result) else result = "message"
|
||||
}
|
||||
|
||||
/** Gets a data flow node representing data sent to the client. */
|
||||
DataFlow::Node getASentItem() {
|
||||
exists(int i |
|
||||
result = getArgument(i) and
|
||||
i >= firstDataIndex and
|
||||
// exclude last argument if it is a callback
|
||||
(
|
||||
i < getNumArgument() - 1 or
|
||||
not result.analyze().getTheType() = TTFunction()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the acknowledgment callback, if any. */
|
||||
DataFlow::FunctionNode getAck() {
|
||||
// acknowledgments are only available when sending through a socket
|
||||
exists(getSocket()) and
|
||||
result = getLastArgument().getALocalSource()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
| tst.js:25:10:25:19 | io.sockets |
|
||||
| tst.js:26:1:26:10 | io.of("/") |
|
||||
| tst.js:27:1:27:12 | ns.use(auth) |
|
||||
| tst.js:28:1:28:11 | ns.to(room) |
|
||||
| tst.js:29:1:29:11 | ns.in(room) |
|
||||
| tst.js:30:1:30:28 | ns.emit ... event') |
|
||||
| tst.js:31:1:31:20 | ns.send('a message') |
|
||||
| tst.js:32:1:32:21 | ns.writ ... ssage') |
|
||||
| tst.js:33:1:33:14 | ns.clients(cb) |
|
||||
| tst.js:34:1:34:17 | ns.compress(true) |
|
||||
| tst.js:35:1:35:16 | ns.binary(false) |
|
||||
| tst.js:36:1:36:12 | io.use(auth) |
|
||||
| tst.js:37:1:37:11 | io.to(room) |
|
||||
| tst.js:38:1:38:11 | io.in(room) |
|
||||
| tst.js:39:1:39:31 | io.emit ... ssage') |
|
||||
| tst.js:40:1:40:20 | io.send('a message') |
|
||||
| tst.js:41:1:41:21 | io.writ ... ssage') |
|
||||
| tst.js:42:1:42:14 | io.clients(cb) |
|
||||
| tst.js:43:1:43:17 | io.compress(true) |
|
||||
| tst.js:44:1:44:16 | io.binary(false) |
|
||||
| tst.js:45:1:45:7 | ns.json |
|
||||
| tst.js:46:1:46:11 | ns.volatile |
|
||||
| tst.js:47:1:47:8 | ns.local |
|
||||
| tst.js:50:1:66:2 | io.on(' ... cal;\\n}) |
|
||||
| tst.js:67:1:67:35 | io.on(' ... => {}) |
|
||||
| tst.js:68:1:68:32 | ns.on(' ... => {}) |
|
||||
| tst.js:69:1:73:2 | ns.on(' ... {});\\n}) |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from SocketIO::NamespaceNode ns
|
||||
select ns
|
||||
@@ -0,0 +1,3 @@
|
||||
| tst.js:70:3:70:35 | socket. ... => {}) | tst.js:69:22:69:27 | socket |
|
||||
| tst.js:71:3:71:46 | socket. ... => {}) | tst.js:69:22:69:27 | socket |
|
||||
| tst.js:72:3:72:43 | socket. ... => {}) | tst.js:69:22:69:27 | socket |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from SocketIO::ReceiveNode rn
|
||||
select rn, rn.getSocket()
|
||||
@@ -0,0 +1,3 @@
|
||||
| tst.js:70:3:70:35 | socket. ... => {}) | tst.js:70:25:70:27 | msg |
|
||||
| tst.js:71:3:71:46 | socket. ... => {}) | tst.js:71:27:71:31 | data1 |
|
||||
| tst.js:71:3:71:46 | socket. ... => {}) | tst.js:71:34:71:38 | data2 |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from SocketIO::ReceiveNode rn
|
||||
select rn, rn.getAReceivedItem()
|
||||
@@ -0,0 +1,2 @@
|
||||
| tst.js:70:3:70:35 | socket. ... => {}) | message |
|
||||
| tst.js:71:3:71:46 | socket. ... => {}) | message |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from SocketIO::ReceiveNode rn
|
||||
select rn, rn.getEventName()
|
||||
@@ -0,0 +1,9 @@
|
||||
| tst.js:30:1:30:28 | ns.emit ... event') |
|
||||
| tst.js:31:1:31:20 | ns.send('a message') |
|
||||
| tst.js:32:1:32:21 | ns.writ ... ssage') |
|
||||
| tst.js:39:1:39:31 | io.emit ... ssage') |
|
||||
| tst.js:40:1:40:20 | io.send('a message') |
|
||||
| tst.js:41:1:41:21 | io.writ ... ssage') |
|
||||
| tst.js:51:3:51:22 | socket.emit('event') |
|
||||
| tst.js:54:3:54:43 | socket. ... => {}) |
|
||||
| tst.js:55:3:55:27 | socket. ... ssage') |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from SocketIO::SendNode sn
|
||||
select sn
|
||||
@@ -0,0 +1,9 @@
|
||||
| tst.js:30:1:30:28 | ns.emit ... event') | tst.js:30:18:30:27 | 'an event' |
|
||||
| tst.js:31:1:31:20 | ns.send('a message') | tst.js:31:9:31:19 | 'a message' |
|
||||
| tst.js:32:1:32:21 | ns.writ ... ssage') | tst.js:32:10:32:20 | 'a message' |
|
||||
| tst.js:39:1:39:31 | io.emit ... ssage') | tst.js:39:20:39:30 | 'a message' |
|
||||
| tst.js:40:1:40:20 | io.send('a message') | tst.js:40:9:40:19 | 'a message' |
|
||||
| tst.js:41:1:41:21 | io.writ ... ssage') | tst.js:41:10:41:20 | 'a message' |
|
||||
| tst.js:54:3:54:43 | socket. ... => {}) | tst.js:54:15:54:17 | 'a' |
|
||||
| tst.js:54:3:54:43 | socket. ... => {}) | tst.js:54:20:54:28 | 'message' |
|
||||
| tst.js:55:3:55:27 | socket. ... ssage') | tst.js:55:16:55:26 | 'a message' |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from SocketIO::SendNode sn
|
||||
select sn, sn.getASentItem()
|
||||
@@ -0,0 +1 @@
|
||||
| tst.js:54:3:54:43 | socket. ... => {}) | tst.js:54:31:54:42 | (data) => {} |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from SocketIO::SendNode sn
|
||||
select sn, sn.getAck()
|
||||
@@ -0,0 +1,3 @@
|
||||
| tst.js:51:3:51:22 | socket.emit('event') | tst.js:50:19:50:24 | socket |
|
||||
| tst.js:54:3:54:43 | socket. ... => {}) | tst.js:50:19:50:24 | socket |
|
||||
| tst.js:55:3:55:27 | socket. ... ssage') | tst.js:50:19:50:24 | socket |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from SocketIO::SendNode sn
|
||||
select sn, sn.getSocket()
|
||||
@@ -0,0 +1,12 @@
|
||||
| tst.js:1:12:1:33 | require ... .io')() |
|
||||
| tst.js:4:13:4:24 | new Server() |
|
||||
| tst.js:6:13:6:27 | Server.listen() |
|
||||
| tst.js:9:1:9:21 | io.serv ... (false) |
|
||||
| tst.js:10:1:10:21 | io.set( ... s', []) |
|
||||
| tst.js:11:1:11:21 | io.path ... npath') |
|
||||
| tst.js:12:1:12:15 | io.adapter(foo) |
|
||||
| tst.js:13:1:13:14 | io.origins([]) |
|
||||
| tst.js:14:1:14:15 | io.listen(http) |
|
||||
| tst.js:15:1:15:15 | io.attach(http) |
|
||||
| tst.js:16:1:16:15 | io.bind(engine) |
|
||||
| tst.js:17:1:17:23 | io.onco ... socket) |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from SocketIO::ServerNode srv
|
||||
select srv
|
||||
@@ -0,0 +1,21 @@
|
||||
| tst.js:50:19:50:24 | socket |
|
||||
| tst.js:51:3:51:22 | socket.emit('event') |
|
||||
| tst.js:52:3:52:17 | socket.to(room) |
|
||||
| tst.js:53:3:53:17 | socket.in(room) |
|
||||
| tst.js:54:3:54:43 | socket. ... => {}) |
|
||||
| tst.js:55:3:55:27 | socket. ... ssage') |
|
||||
| tst.js:56:3:56:19 | socket.join(room) |
|
||||
| tst.js:57:3:57:20 | socket.leave(room) |
|
||||
| tst.js:58:3:58:16 | socket.use(cb) |
|
||||
| tst.js:59:3:59:23 | socket. ... s(true) |
|
||||
| tst.js:60:3:60:22 | socket.binary(false) |
|
||||
| tst.js:61:3:61:25 | socket. ... t(true) |
|
||||
| tst.js:62:3:62:13 | socket.json |
|
||||
| tst.js:63:3:63:17 | socket.volatile |
|
||||
| tst.js:64:3:64:18 | socket.broadcast |
|
||||
| tst.js:65:3:65:14 | socket.local |
|
||||
| tst.js:67:22:67:27 | socket |
|
||||
| tst.js:68:19:68:24 | socket |
|
||||
| tst.js:69:22:69:27 | socket |
|
||||
| tst.js:70:3:70:35 | socket. ... => {}) |
|
||||
| tst.js:71:3:71:46 | socket. ... => {}) |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from SocketIO::SocketNode sn
|
||||
select sn
|
||||
73
javascript/ql/test/library-tests/frameworks/SocketIO/tst.js
Normal file
73
javascript/ql/test/library-tests/frameworks/SocketIO/tst.js
Normal file
@@ -0,0 +1,73 @@
|
||||
const io = require('socket.io')(); // SocketIO::ServerNode
|
||||
|
||||
const Server = require('socket.io');
|
||||
const io2 = new Server(); // SocketIO::ServerNode
|
||||
|
||||
const io3 = Server.listen(); // SocketIO::ServerNode
|
||||
|
||||
// more SocketIO::ServerNodes:
|
||||
io.serveClient(false);
|
||||
io.set('origins', []);
|
||||
io.path('/myownpath');
|
||||
io.adapter(foo);
|
||||
io.origins([]);
|
||||
io.listen(http);
|
||||
io.attach(http);
|
||||
io.bind(engine);
|
||||
io.onconnection(socket);
|
||||
|
||||
// not SocketIO::ServerNodes:
|
||||
io.path();
|
||||
io.adapter();
|
||||
io.origins();
|
||||
|
||||
// SocketIO::NamespaceNodes:
|
||||
var ns = io.sockets;
|
||||
io.of("/");
|
||||
ns.use(auth);
|
||||
ns.to(room);
|
||||
ns.in(room);
|
||||
ns.emit('event', 'an event');
|
||||
ns.send('a message');
|
||||
ns.write('a message');
|
||||
ns.clients(cb);
|
||||
ns.compress(true);
|
||||
ns.binary(false);
|
||||
io.use(auth);
|
||||
io.to(room);
|
||||
io.in(room);
|
||||
io.emit('message', 'a message');
|
||||
io.send('a message');
|
||||
io.write('a message');
|
||||
io.clients(cb);
|
||||
io.compress(true);
|
||||
io.binary(false);
|
||||
ns.json;
|
||||
ns.volatile;
|
||||
ns.local;
|
||||
|
||||
// SocketIO::SocketNodes:
|
||||
io.on('connect', (socket) => {
|
||||
socket.emit('event');
|
||||
socket.to(room);
|
||||
socket.in(room);
|
||||
socket.send('a', 'message', (data) => {});
|
||||
socket.write('a message');
|
||||
socket.join(room);
|
||||
socket.leave(room);
|
||||
socket.use(cb);
|
||||
socket.compress(true);
|
||||
socket.binary(false);
|
||||
socket.disconnect(true);
|
||||
socket.json;
|
||||
socket.volatile;
|
||||
socket.broadcast;
|
||||
socket.local;
|
||||
});
|
||||
io.on('connection', (socket) => {});
|
||||
ns.on('connect', (socket) => {});
|
||||
ns.on('connection', (socket) => {
|
||||
socket.on('message', (msg) => {});
|
||||
socket.once('message', (data1, data2) => {});
|
||||
socket.addListener(eventName(), () => {});
|
||||
});
|
||||
@@ -45,6 +45,9 @@ nodes
|
||||
| mongooseJsonParse.js:20:19:20:50 | JSON.pa ... ).title |
|
||||
| mongooseJsonParse.js:20:30:20:43 | req.query.data |
|
||||
| mongooseJsonParse.js:23:19:23:23 | query |
|
||||
| socketio.js:10:25:10:30 | handle |
|
||||
| socketio.js:11:12:11:53 | `INSERT ... andle}` |
|
||||
| socketio.js:11:46:11:51 | handle |
|
||||
| tst2.js:9:27:9:78 | "select ... rams.id |
|
||||
| tst2.js:9:27:9:84 | "select ... d + "'" |
|
||||
| tst2.js:9:66:9:78 | req.params.id |
|
||||
@@ -125,6 +128,8 @@ edges
|
||||
| mongooseJsonParse.js:20:19:20:50 | JSON.pa ... ).title | mongooseJsonParse.js:19:19:19:20 | {} |
|
||||
| mongooseJsonParse.js:20:19:20:50 | JSON.pa ... ).title | mongooseJsonParse.js:23:19:23:23 | query |
|
||||
| mongooseJsonParse.js:20:30:20:43 | req.query.data | mongooseJsonParse.js:20:19:20:44 | JSON.pa ... y.data) |
|
||||
| socketio.js:10:25:10:30 | handle | socketio.js:11:46:11:51 | handle |
|
||||
| socketio.js:11:46:11:51 | handle | socketio.js:11:12:11:53 | `INSERT ... andle}` |
|
||||
| tst2.js:9:27:9:78 | "select ... rams.id | tst2.js:9:27:9:84 | "select ... d + "'" |
|
||||
| tst2.js:9:66:9:78 | req.params.id | tst2.js:9:27:9:78 | "select ... rams.id |
|
||||
| tst3.js:8:7:9:55 | query1 | tst3.js:10:14:10:19 | query1 |
|
||||
@@ -154,6 +159,7 @@ edges
|
||||
| mongoose.js:60:25:60:29 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:60:25:60:29 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
|
||||
| mongoose.js:63:24:63:28 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:63:24:63:28 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
|
||||
| mongooseJsonParse.js:23:19:23:23 | query | mongooseJsonParse.js:20:30:20:43 | req.query.data | mongooseJsonParse.js:23:19:23:23 | query | This query depends on $@. | mongooseJsonParse.js:20:30:20:43 | req.query.data | a user-provided value |
|
||||
| socketio.js:11:12:11:53 | `INSERT ... andle}` | socketio.js:10:25:10:30 | handle | socketio.js:11:12:11:53 | `INSERT ... andle}` | This query depends on $@. | socketio.js:10:25:10:30 | handle | a user-provided value |
|
||||
| tst2.js:9:27:9:84 | "select ... d + "'" | tst2.js:9:66:9:78 | req.params.id | tst2.js:9:27:9:84 | "select ... d + "'" | This query depends on $@. | tst2.js:9:66:9:78 | req.params.id | a user-provided value |
|
||||
| tst3.js:10:14:10:19 | query1 | tst3.js:9:16:9:34 | req.params.category | tst3.js:10:14:10:19 | query1 | This query depends on $@. | tst3.js:9:16:9:34 | req.params.category | a user-provided value |
|
||||
| tst4.js:8:10:8:66 | 'SELECT ... d + '"' | tst4.js:8:46:8:60 | $routeParams.id | tst4.js:8:10:8:66 | 'SELECT ... d + '"' | This query depends on $@. | tst4.js:8:46:8:60 | $routeParams.id | a user-provided value |
|
||||
|
||||
13
javascript/ql/test/query-tests/Security/CWE-089/socketio.js
Normal file
13
javascript/ql/test/query-tests/Security/CWE-089/socketio.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// Adapted from https://github.com/mapbox/node-sqlite3/wiki/API, which is
|
||||
// part of the node-sqlite3 project, which is licensed under the BSD 3-Clause
|
||||
// License; see file node-sqlite3-LICENSE.
|
||||
var express = require('express');
|
||||
var sqlite3 = require('sqlite3').verbose();
|
||||
var db = new sqlite3.Database(':memory:');
|
||||
|
||||
var io = require('socket.io')();
|
||||
io.on('connection', (socket) => {
|
||||
socket.on('newuser', (handle) => {
|
||||
db.run(`INSERT INTO users(name) VALUES ${handle}`);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user