You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi, my code is fairly simple, using pymysql within the Flask framework, but I have been unable to detect SQL injection. By using pyre_dump() and reveal_type(), I have identified the following issues
with pyre_dump(), I got the exception result: Resolved type for base pymysql is unknown , as below:
2024-04-24 09:56:02,141 [PID 6032] WARNING Checking if cursors is an attribute, property or global variable. Resolved type for base pymysql is unknown
2024-04-24 09:56:02,144 [PID 6032] WARNING Resolved callees for expression pymysql.cursors:
2024-04-24 09:56:02,145 [PID 6032] WARNING { call = None;
2024-04-24 09:56:02,146 [PID 6032] WARNING attribute_access =
2024-04-24 09:56:02,146 [PID 6032] WARNING (Some { property_targets = []; global_targets = []; is_attribute = true });
2024-04-24 09:56:02,146 [PID 6032] WARNING identifier = None; string_format = None }
2024-04-24 09:56:02,147 [PID 6032] WARNING Checking if DictCursor is an attribute, property or global variable. Resolved type for base pymysql.cursors is unknown
2024-04-24 09:56:02,147 [PID 6032] WARNING Resolved callees for expression pymysql.cursors.DictCursor:
2024-04-24 09:56:02,148 [PID 6032] WARNING { call = None;
2024-04-24 09:56:02,149 [PID 6032] WARNING attribute_access =
2024-04-24 09:56:02,150 [PID 6032] WARNING (Some { property_targets = []; global_targets = []; is_attribute = true });
2024-04-24 09:56:02,151 [PID 6032] WARNING identifier = None; string_format = None }
2024-04-24 09:56:02,151 [PID 6032] WARNING Resolving function call pymysql.connect($parameter$host = "localhost", $parameter$user = "user", $parameter$password = "passwd", $parameter$database = "db", $parameter$cursorclass = pymysql.cursors.DictCursor)
2024-04-24 09:56:02,151 [PID 6032] WARNING Checking if "localhost" is a callable, resolved type is typing_extensions.Literal['localhost']
2024-04-24 09:56:02,152 [PID 6032] WARNING Checking if "user" is a callable, resolved type is typing_extensions.Literal['user']
2024-04-24 09:56:02,152 [PID 6032] WARNING Checking if "passwd" is a callable, resolved type is typing_extensions.Literal['passwd']
2024-04-24 09:56:02,153 [PID 6032] WARNING Checking if "db" is a callable, resolved type is typing_extensions.Literal['db']
2024-04-24 09:56:02,154 [PID 6032] WARNING Checking if pymysql.cursors.DictCursor is a callable, resolved type is typing.Type[pymysql.cursors.DictCursor]
2024-04-24 09:56:02,155 [PID 6032] WARNING Resolved callee from its resolved type:
2024-04-24 09:56:02,156 [PID 6032] WARNING { call_targets = []; 2024-04-24 09:56:02,157 [PID 6032] WARNING new_targets = 2024-04-24 09:56:02,158 [PID 6032] WARNING [{ target = 2024-04-24 09:56:02,159 [PID 6032] WARNING (Method 2024-04-24 09:56:02,160 [PID 6032] WARNING { class_name = "object"; method_name = "__new__"; kind = Normal }); 2024-04-24 09:56:02,161 [PID 6032] WARNING implicit_self = true; implicit_dunder_call = false; index = 0; 2024-04-24 09:56:02,161 [PID 6032] WARNING return_type = (Some {}); receiver_class = None } 2024-04-24 09:56:02,162 [PID 6032] WARNING ]; 2024-04-24 09:56:02,162 [PID 6032] WARNING init_targets = 2024-04-24 09:56:02,163 [PID 6032] WARNING [{ target = 2024-04-24 09:56:02,163 [PID 6032] WARNING (Method 2024-04-24 09:56:02,164 [PID 6032] WARNING { class_name = "pymysql.cursors.Cursor"; method_name = "__init__"; 2024-04-24 09:56:02,165 [PID 6032] WARNING kind = Normal }); 2024-04-24 09:56:02,165 [PID 6032] WARNING implicit_self = true; implicit_dunder_call = false; index = 0; 2024-04-24 09:56:02,167 [PID 6032] WARNING return_type = (Some {}); receiver_class = None } 2024-04-24 09:56:02,167 [PID 6032] WARNING ]; 2024-04-24 09:56:02,168 [PID 6032] WARNING higher_order_parameters = {}; unresolved = false }
2024-04-24 09:56:02,170 [PID 6032] WARNING Checking if pymysql.connect is a callable, resolved type is typing.Any
After removing the pyre_dump statement, the results obtained from reveal_type / reveal_taint are as follows. It can be seen that the pymysql sink cannot be captured:
Hey! It seems the issue you're encountering with pyre-check when using pymysql may stem from outdated or incomplete type stubs in the library, which hinders the tool's ability to accurately recognize and handle types like pymysql.cursors.DictCursor. This issue can prevent pyre-check from effectively tracking taints and resolving types, thereby affecting its ability to detect vulnerabilities like SQL injection, which you observed works correctly with django.db. To address this, you might consider updating the stubs or configurations in pyre-check to better recognize pymysql components, or consult the Pyre project documentation for guidance on enhancing type support.
I have already tried to update the type stubs of pymysql from git repository before I posted this issue. But it still didn't work. Maybe you can run the pyre to analyze my source code I mentioned above to see if you can figure out this problem.
Hi, my code is fairly simple, using pymysql within the Flask framework, but I have been unable to detect SQL injection. By using pyre_dump() and reveal_type(), I have identified the following issues
source code
issues
pymysql
isunknown
, as below:2024-04-24 09:56:02,141 [PID 6032] WARNING Checking if
cursors
is an attribute, property or global variable. Resolved type for basepymysql
isunknown
2024-04-24 09:56:02,144 [PID 6032] WARNING Resolved callees for expression
pymysql.cursors
:2024-04-24 09:56:02,145 [PID 6032] WARNING { call = None;
2024-04-24 09:56:02,146 [PID 6032] WARNING attribute_access =
2024-04-24 09:56:02,146 [PID 6032] WARNING (Some { property_targets = []; global_targets = []; is_attribute = true });
2024-04-24 09:56:02,146 [PID 6032] WARNING identifier = None; string_format = None }
2024-04-24 09:56:02,147 [PID 6032] WARNING Checking if
DictCursor
is an attribute, property or global variable. Resolved type for basepymysql.cursors
isunknown
2024-04-24 09:56:02,147 [PID 6032] WARNING Resolved callees for expression
pymysql.cursors.DictCursor
:2024-04-24 09:56:02,148 [PID 6032] WARNING { call = None;
2024-04-24 09:56:02,149 [PID 6032] WARNING attribute_access =
2024-04-24 09:56:02,150 [PID 6032] WARNING (Some { property_targets = []; global_targets = []; is_attribute = true });
2024-04-24 09:56:02,151 [PID 6032] WARNING identifier = None; string_format = None }
2024-04-24 09:56:02,151 [PID 6032] WARNING Resolving function call
pymysql.connect($parameter$host = "localhost", $parameter$user = "user", $parameter$password = "passwd", $parameter$database = "db", $parameter$cursorclass = pymysql.cursors.DictCursor)
2024-04-24 09:56:02,151 [PID 6032] WARNING Checking if
"localhost"
is a callable, resolved type istyping_extensions.Literal['localhost']
2024-04-24 09:56:02,152 [PID 6032] WARNING Checking if
"user"
is a callable, resolved type istyping_extensions.Literal['user']
2024-04-24 09:56:02,152 [PID 6032] WARNING Checking if
"passwd"
is a callable, resolved type istyping_extensions.Literal['passwd']
2024-04-24 09:56:02,153 [PID 6032] WARNING Checking if
"db"
is a callable, resolved type istyping_extensions.Literal['db']
2024-04-24 09:56:02,154 [PID 6032] WARNING Checking if
pymysql.cursors.DictCursor
is a callable, resolved type istyping.Type[pymysql.cursors.DictCursor]
2024-04-24 09:56:02,155 [PID 6032] WARNING Resolved callee from its resolved type:
2024-04-24 09:56:02,156 [PID 6032] WARNING
{ call_targets = []; 2024-04-24 09:56:02,157 [PID 6032] WARNING new_targets = 2024-04-24 09:56:02,158 [PID 6032] WARNING [{ target = 2024-04-24 09:56:02,159 [PID 6032] WARNING (Method 2024-04-24 09:56:02,160 [PID 6032] WARNING { class_name = "object"; method_name = "__new__"; kind = Normal }); 2024-04-24 09:56:02,161 [PID 6032] WARNING implicit_self = true; implicit_dunder_call = false; index = 0; 2024-04-24 09:56:02,161 [PID 6032] WARNING return_type = (Some {}); receiver_class = None } 2024-04-24 09:56:02,162 [PID 6032] WARNING ]; 2024-04-24 09:56:02,162 [PID 6032] WARNING init_targets = 2024-04-24 09:56:02,163 [PID 6032] WARNING [{ target = 2024-04-24 09:56:02,163 [PID 6032] WARNING (Method 2024-04-24 09:56:02,164 [PID 6032] WARNING { class_name = "pymysql.cursors.Cursor"; method_name = "__init__"; 2024-04-24 09:56:02,165 [PID 6032] WARNING kind = Normal }); 2024-04-24 09:56:02,165 [PID 6032] WARNING implicit_self = true; implicit_dunder_call = false; index = 0; 2024-04-24 09:56:02,167 [PID 6032] WARNING return_type = (Some {}); receiver_class = None } 2024-04-24 09:56:02,167 [PID 6032] WARNING ]; 2024-04-24 09:56:02,168 [PID 6032] WARNING higher_order_parameters = {}; unresolved = false }
2024-04-24 09:56:02,170 [PID 6032] WARNING Checking if
pymysql.connect
is a callable, resolved type istyping.Any
2024-04-24 10:13:11,594 [PID 6426] WARNING djangosql.main:15:4-15:15: Revealed type for sql: typing.Any
2024-04-24 10:13:11,594 [PID 6426] WARNING djangosql.main:16:4-16:16: Revealed forward taint for
sql
: {CallSite(callees=[djangosql.main.request_parse], location=djangosql.main:13:10-13:32, port=result) -> LocalTaint(Kinds: {UserControlled -> Frame(Breadcrumb: [ModelShaping(-), TitoBroadening(-), Tito(-), Broadening(-), ModelTitoShaping(-), ObscureUnknownCallee(-)], TraceLength: 1, LeafName: [LeafName(djangosql.main.request_parse, port=Leaf(req_data)), LeafName(werkzeug.wrappers.request.Request.get_data, port=Leaf(return)), LeafName(werkzeug.wrappers.request.Request.get_json, port=Leaf(return))], FirstField: ["args"])}, Breadcrumb: [], FirstIndex: ["sql"], CallInfoIntervals: [caller_interval: receiver_interval: is_self_call: false])}2024-04-24 10:13:11,594 [PID 6426] WARNING djangosql.main:19:4-19:15: Revealed type for cursor: typing.Any
2024-04-24 10:13:11,595 [PID 6426] WARNING djangosql.main:20:4-20:16: Revealed forward taint for
cursor
: {}2024-04-24 10:13:11,595 [PID 6426] WARNING djangosql.main:20:4-20:24: Revealed backward taint for
cursor
: {}2024-04-24 10:13:11,595 [PID 6426] WARNING djangosql.main:16:4-16:21: Revealed backward taint for
sql
: {}2024-04-24 10:13:11,595 [PID 6426] WARNING flasksql.main:26:4-26:15: Revealed type for sql: typing.Any
2024-04-24 10:13:11,595 [PID 6426] WARNING flasksql.main:27:4-27:16: Revealed forward taint for
sql
: {CallSite(callees=[flasksql.main.request_parse], location=flasksql.main:23:10-23:32, port=result) -> LocalTaint(Kinds: {UserControlled -> Frame(Breadcrumb: [ObscureUnknownCallee(-)], TraceLength: 1, LeafName: [LeafName(werkzeug.wrappers.request.Request.get_data, port=Leaf(return)), LeafName(werkzeug.wrappers.request.Request.get_json, port=Leaf(return))])}, Breadcrumb: [], FirstIndex: ["sql"], CallInfoIntervals: [caller_interval: receiver_interval: is_self_call: false])}2024-04-24 10:13:11,596 [PID 6426] WARNING flasksql.main:37:8-37:19: Revealed type for db: typing.Any
2024-04-24 10:13:11,596 [PID 6426] WARNING flasksql.main:38:8-38:20: Revealed forward taint for
db
: {}2024-04-24 10:13:11,596 [PID 6426] WARNING flasksql.main:40:8-40:19: Revealed type for sql: typing.Any
2024-04-24 10:13:11,596 [PID 6426] WARNING flasksql.main:41:8-41:20: Revealed forward taint for
sql
: {CallSite(callees=[flasksql.main.request_parse], location=flasksql.main:23:10-23:32, port=result) -> LocalTaint(Kinds: {UserControlled -> Frame(Breadcrumb: [ObscureUnknownCallee(-)], TraceLength: 1, LeafName: [LeafName(werkzeug.wrappers.request.Request.get_data, port=Leaf(return)), LeafName(werkzeug.wrappers.request.Request.get_json, port=Leaf(return))])}, Breadcrumb: [], FirstIndex: ["sql"], CallInfoIntervals: [caller_interval: receiver_interval: is_self_call: false])}2024-04-24 10:13:11,597 [PID 6426] INFO Processed 43 of 43 callables
2024-04-24 10:13:11,597 [PID 6426] INFO Iteration #0, 43 callables, heap size 0.371GB took 0.05s
2024-04-24 10:13:11,597 [PID 6426] INFO Iteration #1. 30 callables [...]
2024-04-24 10:13:11,598 [PID 6426] WARNING djangosql.main:15:4-15:15: Revealed type for sql: typing.Any
2024-04-24 10:13:11,598 [PID 6426] WARNING djangosql.main:16:4-16:16: Revealed forward taint for
sql
: {CallSite(callees=[djangosql.main.request_parse], location=djangosql.main:13:10-13:32, port=result) -> LocalTaint(Kinds: {UserControlled -> Frame(Breadcrumb: [ModelShaping(-), TitoBroadening(-), Tito(-), Broadening(-), ModelTitoShaping(-), ObscureUnknownCallee(-)], TraceLength: 1, LeafName: [LeafName(djangosql.main.request_parse, port=Leaf(req_data)), LeafName(werkzeug.wrappers.request.Request.get_data, port=Leaf(return)), LeafName(werkzeug.wrappers.request.Request.get_json, port=Leaf(return))], FirstField: ["args"])}, Breadcrumb: [], FirstIndex: ["sql"], CallInfoIntervals: [caller_interval: receiver_interval: is_self_call: false])}2024-04-24 10:13:11,598 [PID 6426] WARNING djangosql.main:19:4-19:15: Revealed type for cursor: typing.Any
2024-04-24 10:13:11,599 [PID 6426] WARNING djangosql.main:20:4-20:16: Revealed forward taint for
cursor
: {}2024-04-24 10:13:11,599 [PID 6426] WARNING djangosql.main:20:4-20:24: Revealed backward taint for
cursor
: {}2024-04-24 10:13:11,599 [PID 6426] WARNING djangosql.main:16:4-16:21: Revealed backward taint for
sql
: {}2024-04-24 10:13:11,600 [PID 6426] WARNING flasksql.main:26:4-26:15: Revealed type for sql: typing.Any
2024-04-24 10:13:11,600 [PID 6426] WARNING flasksql.main:27:4-27:16: Revealed forward taint for
sql
: {CallSite(callees=[flasksql.main.request_parse], location=flasksql.main:23:10-23:32, port=result) -> LocalTaint(Kinds: {UserControlled -> Frame(Breadcrumb: [ObscureUnknownCallee(-)], TraceLength: 1, LeafName: [LeafName(werkzeug.wrappers.request.Request.get_data, port=Leaf(return)), LeafName(werkzeug.wrappers.request.Request.get_json, port=Leaf(return))])}, Breadcrumb: [], FirstIndex: ["sql"], CallInfoIntervals: [caller_interval: receiver_interval: is_self_call: false])}2024-04-24 10:13:11,600 [PID 6426] WARNING flasksql.main:37:8-37:19: Revealed type for db: typing.Any
2024-04-24 10:13:11,600 [PID 6426] WARNING flasksql.main:38:8-38:20: Revealed forward taint for
db
: {}2024-04-24 10:13:11,601 [PID 6426] WARNING flasksql.main:40:8-40:19: Revealed type for sql: typing.Any
2024-04-24 10:13:11,601 [PID 6426] WARNING flasksql.main:41:8-41:20: Revealed forward taint for
sql
: {CallSite(callees=[flasksql.main.request_parse], location=flasksql.main:23:10-23:32, port=result) -> LocalTaint(Kinds: {UserControlled -> Frame(Breadcrumb: [ObscureUnknownCallee(-)], TraceLength: 1, LeafName: [LeafName(werkzeug.wrappers.request.Request.get_data, port=Leaf(return)), LeafName(werkzeug.wrappers.request.Request.get_json, port=Leaf(return))])}, Breadcrumb: [], FirstIndex: ["sql"], CallInfoIntervals: [caller_interval: receiver_interval: is_self_call: false])}2024-04-24 10:13:11,601 [PID 6426] INFO Processed 30 of 30 callables
2024-04-24 10:13:11,602 [PID 6426] INFO Iteration #1, 30 callables, heap size 0.371GB took 0.03s
2024-04-24 10:13:11,602 [PID 6426] INFO Post-processing issues for multi-source rules...
2024-04-24 10:13:11,602 [PID 6426] PERFORMANCE Finished issue post-processing for multi-source rules: 0.197s
2024-04-24 10:13:11,603 [PID 6426] INFO Found 0 issues
2024-04-24 10:13:11,603 [PID 6426] PERFORMANCE Analysis fixpoint complete (iterations: 2, heap size: 370619776, issues: 0): 2.128s
2024-04-24 10:13:11,603 [PID 6426] PERFORMANCE Analyze: 80.480s
[]
Additional information
I look forward to your prompt reply and would greatly appreciate it.
The text was updated successfully, but these errors were encountered: