Skip to content

Commit fde8f93

Browse files
committed
validate variable names in copyToGlobals debug handler
1 parent 6301f3a commit fde8f93

2 files changed

Lines changed: 27 additions & 0 deletions

File tree

ipykernel/debugger.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,15 @@ async def copyToGlobals(self, message):
676676
src_var_name = message["arguments"]["srcVariableName"]
677677
src_frame_id = message["arguments"]["srcFrameId"]
678678

679+
if not str.isidentifier(dst_var_name) or not str.isidentifier(src_var_name):
680+
return {
681+
"type": "response",
682+
"request_seq": message["seq"],
683+
"success": False,
684+
"command": message["command"],
685+
"message": "dstVariableName and srcVariableName must be valid identifiers",
686+
}
687+
679688
expression = f"globals()['{dst_var_name}']"
680689
seq = message["seq"]
681690
return await self._forward_message(

tests/test_debugger.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,24 @@ def my_test():
473473
assert global_var["value"] == local_var["value"] and global_var["type"] == local_var["type"] # noqa: PT018
474474

475475

476+
def test_copy_to_globals_rejects_non_identifier(kernel_with_debug):
477+
# A dstVariableName that is not a valid identifier would break out of the
478+
# single-quoted globals()['...'] expression forwarded to setExpression.
479+
reply = wait_for_debug_request(
480+
kernel_with_debug,
481+
"copyToGlobals",
482+
{
483+
"srcVariableName": "src",
484+
"dstVariableName": "x'] or __import__('os').system('echo pwned') or globals()['y",
485+
"srcFrameId": 0,
486+
},
487+
)
488+
# The request is rejected locally instead of being forwarded to
489+
# setExpression, so the response still carries the copyToGlobals command.
490+
assert reply["success"] is False
491+
assert reply["command"] == "copyToGlobals"
492+
493+
476494
def test_debug_requests_sequential(kernel_with_debug):
477495
# Issue https://github.com/ipython/ipykernel/issues/1412
478496
# Control channel requests should be executed sequentially not concurrently.

0 commit comments

Comments
 (0)