-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Python: Refine the location of flask.request
flow sources
#20281
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?
Python: Refine the location of flask.request
flow sources
#20281
Conversation
The `flask.request` global object is commonly used in request handlers to access data in the active request. In our modelling, we handled this by treating the initial (module-local) definition of `request` as a source of remote flow. In practice this meant a lot of alerts would act as if `from flask import request` was the ultimate "source" of remote flow, and to find the actual request-handler-local instance of `request` one would have to inspect the data-flow path between source and sink. To improve this state of affairs, I have made the following changes to the definition of `FlaskRequestSource`: - We no longer consider `from flask import request` to be a source. - Instead, we look at all places where that `request` value can flow, and include only the ones that are `LocalSourceNode`s (so that inside a request handler, the first occurrence of the `request` object is the source). In practice, this leads to alerts that are much easier to decipher.
As it turns out, referring to the request object using `flask.request` is not uncommon, and this meant restricting to `Name` nodes was too strong. With the changes in this commit, we now include those occurrences as well.
Really starting to regret our widespread use of `flask.request` as _the_ example of a remote flow source.
a842023
to
0f4f909
Compare
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 pull request refines the location of flask.request
flow sources to provide more precise security vulnerability detection. Instead of treating the module-level import from flask import request
as the ultimate source of remote flow, the change identifies the first occurrence of the request
object within specific request handlers as the source.
Key changes:
- Modified
FlaskRequestSource
definition to exclude module-level imports as sources - Added logic to identify
LocalSourceNode
s whererequest
flows within request handlers - Updated expected test results to reflect the more precise source locations
#select | ||
| code_injection.py:7:10:7:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:7:10:7:13 | ControlFlowNode for code | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | | ||
| code_injection.py:8:10:8:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:8:10:8:13 | ControlFlowNode for code | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | | ||
| code_injection.py:10:10:10:12 | ControlFlowNode for cmd | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:10:10:10:12 | ControlFlowNode for cmd | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | | ||
| code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | code_injection.py:18:16:18:22 | ControlFlowNode for request | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | This code execution depends on a $@. | code_injection.py:18:16:18:22 | ControlFlowNode for request | user-provided value | |
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.
[nitpick] The #select
section appears at the beginning of the file rather than at the end, which is unusual for CodeQL test expected files. This ordering deviation could indicate a formatting issue or test structure problem that should be investigated.
#select | |
| code_injection.py:7:10:7:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:7:10:7:13 | ControlFlowNode for code | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | | |
| code_injection.py:8:10:8:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:8:10:8:13 | ControlFlowNode for code | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | | |
| code_injection.py:10:10:10:12 | ControlFlowNode for cmd | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:10:10:10:12 | ControlFlowNode for cmd | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | | |
| code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | code_injection.py:18:16:18:22 | ControlFlowNode for request | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | This code execution depends on a $@. | code_injection.py:18:16:18:22 | ControlFlowNode for request | user-provided value | |
Copilot uses AI. Check for mistakes.
The
flask.request
global object is commonly used in request handlers to access data in the active request. In our modelling, we handled this by treating the initial (module-local) definition ofrequest
as a source of remote flow. In practice this meant a lot of alerts would act as iffrom flask import request
was the ultimate "source" of remote flow, and to find the actual request-handler-local instance ofrequest
one would have to inspect the data-flow path between source and sink.To improve this state of affairs, I have made the following changes to the definition of
FlaskRequestSource
:from flask import request
to be a source.request
value can flow, and include only the ones that areLocalSourceNode
s (so that inside a request handler, the first occurrence of therequest
object is the source).In practice, this leads to alerts that are much easier to decipher.