-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Python: Add models for socketio #20914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds support for the python-socketio library by modeling remote flow sources and request handlers. The implementation enables CodeQL to track tainted data flowing through Socket.IO event handlers and callbacks.
Key Changes
- Added comprehensive models for
python-socketioServer, AsyncServer, Namespace, and AsyncNamespace classes - Identified Socket.IO event handlers and callbacks as request handlers with appropriate routed parameters
- Modeled the return value of
call()methods as remote flow sources
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| python/ql/lib/semmle/python/frameworks/Socketio.qll | Core implementation providing models for Socket.IO servers, event handlers, callbacks, and remote flow sources |
| python/ql/lib/semmle/python/Frameworks.qll | Added import for the new Socketio module in alphabetical order |
| python/ql/test/library-tests/frameworks/socketio/test.py | Test file covering various Socket.IO event handler patterns including decorators and lambda handlers |
| python/ql/test/library-tests/frameworks/socketio/taint_test.py | Comprehensive taint tracking test covering both sync and async Socket.IO patterns, namespaces, and callbacks |
| python/ql/test/library-tests/frameworks/socketio/InlineTaintTest.ql | Query file for inline taint testing |
| python/ql/test/library-tests/frameworks/socketio/InlineTaintTest.expected | Expected test results for inline taint tests |
| python/ql/test/library-tests/frameworks/socketio/ConceptsTest.ql | Query file for concepts testing |
| python/ql/test/library-tests/frameworks/socketio/ConceptsTest.expected | Expected test results for concepts tests (empty, indicating no failures expected) |
| python/ql/lib/change-notes/2025-11-26-socketio.md | Release note documenting the addition of remote flow sources for python-socketio |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ensure_tainted(data) # $ tainted | ||
| res = sio.call("e1", sid=sid) | ||
| ensure_tainted(res) # $ tainted | ||
| sio.emit("e2", "hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 'lambda' is just a simple wrapper around a callable object. Use that object directly.
| res = sio.call("e1", sid=sid) | ||
| ensure_tainted(res) # $ tainted | ||
| sio.emit("e2", "hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x | ||
| sio.send("hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 'lambda' is just a simple wrapper around a callable object. Use that object directly.
| sio.send("hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x | |
| sio.send("hi", to=sid, callback=ensure_tainted) # $ tainted $ requestHandler routedParameter=x |
| ensure_tainted(data) # $ tainted | ||
| res = self.call("e1", sid=sid) | ||
| ensure_tainted(res) # $ tainted | ||
| self.emit("e2", "hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 'lambda' is just a simple wrapper around a callable object. Use that object directly.
| res = self.call("e1", sid=sid) | ||
| ensure_tainted(res) # $ tainted | ||
| self.emit("e2", "hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x | ||
| self.send("hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 'lambda' is just a simple wrapper around a callable object. Use that object directly.
| self.send("hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x | |
| self.send("hi", to=sid, callback=ensure_tainted) # $ tainted $ requestHandler routedParameter=x |
| ensure_tainted(data) # $ tainted | ||
| res = await asio.call("e1", sid=sid) | ||
| ensure_tainted(res) # $ tainted | ||
| await asio.emit("e2", "hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 'lambda' is just a simple wrapper around a callable object. Use that object directly.
| res = await asio.call("e1", sid=sid) | ||
| ensure_tainted(res) # $ tainted | ||
| await asio.emit("e2", "hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x | ||
| await asio.send("hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 'lambda' is just a simple wrapper around a callable object. Use that object directly.
| await asio.send("hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x | |
| await asio.send("hi", to=sid, callback=ensure_tainted) # $ tainted $ requestHandler routedParameter=x |
| ensure_tainted(data) # $ tainted | ||
| res = await self.call("e1", sid=sid) | ||
| ensure_tainted(res) # $ tainted | ||
| await self.emit("e2", "hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 'lambda' is just a simple wrapper around a callable object. Use that object directly.
| await self.emit("e2", "hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x | |
| await self.emit("e2", "hi", to=sid, callback=ensure_tainted) # $ tainted $ requestHandler routedParameter=x |
| res = await self.call("e1", sid=sid) | ||
| ensure_tainted(res) # $ tainted | ||
| await self.emit("e2", "hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x | ||
| await self.send("hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x |
Copilot
AI
Nov 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 'lambda' is just a simple wrapper around a callable object. Use that object directly.
| await self.send("hi", to=sid, callback=lambda x: ensure_tainted(x)) # $ tainted $ requestHandler routedParameter=x | |
| await self.send("hi", to=sid, callback=ensure_tainted) # $ tainted $ requestHandler routedParameter=x |
Adds remote flow sources for the
python-socketiolibrary.