Skip to content

Commit b0be818

Browse files
Add taint test
1 parent a83c70f commit b0be818

File tree

5 files changed

+68
-13
lines changed

5 files changed

+68
-13
lines changed

python/ql/lib/semmle/python/frameworks/Socketio.qll

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ module SocketIO {
3030
private class EventHandler extends Http::Server::RequestHandler::Range {
3131
EventHandler() {
3232
serverEventAnnotation().getAValueReachableFromSource().asExpr() = this.getADecorator()
33+
or
34+
exists(DataFlow::CallCfgNode c, DataFlow::Node arg | c = server().getMember("on").getACall() |
35+
(
36+
arg = c.getArg(1)
37+
or
38+
arg = c.getArgByName("handler")
39+
) and
40+
poorMansFunctionTracker(this) = arg
41+
)
3342
}
3443

3544
override Parameter getARoutedParameter() {
@@ -44,20 +53,13 @@ module SocketIO {
4453
exists(DataFlow::CallCfgNode c | c = server().getMember(["emit", "send"]).getACall() |
4554
this = c.getArgByName("callback")
4655
)
47-
or
48-
exists(DataFlow::CallCfgNode c | c = server().getMember("on").getACall() |
49-
this = c.getArg(1) or
50-
this = c.getArgByName("handler")
51-
)
5256
}
5357
}
5458

5559
private class CallbackHandler extends Http::Server::RequestHandler::Range {
5660
CallbackHandler() { any(CallbackArgument ca) = poorMansFunctionTracker(this) }
5761

58-
override Parameter getARoutedParameter() {
59-
result = this.getAnArg() and not result = this.getArg(0)
60-
}
62+
override Parameter getARoutedParameter() { result = this.getAnArg() }
6163

6264
override string getFramework() { result = "socketio" }
6365
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
argumentToEnsureNotTaintedNotMarkedAsSpurious
2+
untaintedArgumentToEnsureTaintedNotMarkedAsMissing
3+
testFailures
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import experimental.meta.InlineTaintTest
2+
import MakeInlineTaintTest<TestTaintTrackingConfig>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import sys
2+
import socketio
3+
import sys
4+
5+
def ensure_tainted(*args):
6+
print("tainted", args)
7+
8+
def ensure_not_tainted(*args):
9+
print("not tainted", args)
10+
11+
sio = socketio.Server()
12+
13+
@sio.event
14+
def connect(sid, environ, auth): # $ requestHandler routedParameter=sid routedParameter=environ routedParameter=auth
15+
ensure_not_tainted(sid)
16+
ensure_tainted(environ, # $ tainted
17+
auth) # $ tainted
18+
19+
@sio.event
20+
def event1(sid, data): # $ requestHandler routedParameter=sid routedParameter=data
21+
ensure_not_tainted(sid)
22+
ensure_tainted(data) # $ tainted
23+
res = sio.call("e1", sid=sid)
24+
ensure_tainted(res) # $ tainted
25+
sio.emit("e2", "hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted
26+
sio.send("hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted
27+
28+
asio = socketio.AsyncServer(async_mode='asgi')
29+
30+
@asio.event
31+
async def event2(sid, data): # $ requestHandler routedParameter=sid routedParameter=data
32+
ensure_not_tainted(sid)
33+
ensure_tainted(data) # $ tainted
34+
res = await asio.call("e2", sid=sid)
35+
ensure_tainted(res) # $ tainted
36+
await asio.emit("e3", "hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted
37+
await asio.send("hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted
38+
39+
if __name__ == "__main__":
40+
41+
if "--async" in sys.argv:
42+
import uvicorn
43+
app = socketio.ASGIApp(asio)
44+
uvicorn.run(app, host='127.0.0.1', port=8000)
45+
else:
46+
import eventlet
47+
app = socketio.WSGIApp(sio)
48+
eventlet.wsgi.server(eventlet.listen(('', 8000)), app)

python/ql/test/library-tests/frameworks/socketio/test.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,23 @@
33
sio = socketio.Server()
44

55
@sio.on("connect")
6-
def connect(sid, environ, auth): # $ requestHandler routedParameter=environ routedParameter=auth
6+
def connect(sid, environ, auth): # $ requestHandler routedParameter=sid routedParameter=environ routedParameter=auth
77
print("connect", sid, environ, auth)
88

99
@sio.on("event1")
10-
def handle(sid, data): # $ requestHandler routedParameter=data
10+
def handle(sid, data): # $ requestHandler routedParameter=sid routedParameter=data
1111
print("e1", sid, data)
1212

1313
@sio.event
14-
def event2(sid, data): # $ requestHandler routedParameter=data
14+
def event2(sid, data): # $ requestHandler routedParameter=sid routedParameter=data
1515
print("e2", sid, data)
1616

17-
def event3(sid, data): # $ requestHandler routedParameter=data
17+
def event3(sid, data): # $ requestHandler routedParameter=sid routedParameter=data
1818
print("e3", sid, data)
1919

2020
sio.on("event3", handler=event3)
2121

22-
sio.on("event4", lambda sid,data: print("e4", sid, data)) # $ requestHandler routedParameter=data
22+
sio.on("event4", lambda sid,data: print("e4", sid, data)) # $ requestHandler routedParameter=sid routedParameter=data
2323

2424

2525

0 commit comments

Comments
 (0)