fix: Don't let local codejail exec pollute darklaunched remote globals

We were running local exec before making the copy of globals_dict for
remote_exec, so remote exec has been getting a polluted version of the
globals.
This commit is contained in:
Tim McCormack
2025-04-15 14:16:56 -04:00
parent fd66048a49
commit bf2f8c3705
2 changed files with 22 additions and 2 deletions

View File

@@ -180,6 +180,11 @@ def safe_exec(
else:
# Create a copy so the originals are not modified as part of this call.
# This has to happen before local exec is run, since globals are modified
# as a side effect.
darklaunch_globals = copy.deepcopy(globals_dict)
# Decide which code executor to use.
if unsafely:
exec_fn = codejail_not_safe_exec
@@ -215,8 +220,6 @@ def safe_exec(
# when in darklaunch mode.
if is_codejail_in_darklaunch():
try:
# Create a copy so the originals are not modified as part of this call.
darklaunch_globals = copy.deepcopy(globals_dict)
data = {
"code": code_prolog + LAZY_IMPORTS + code,
"globals_dict": darklaunch_globals,

View File

@@ -1,6 +1,7 @@
"""Test safe_exec.py"""
import copy
import hashlib
import os
import os.path
@@ -216,10 +217,21 @@ class TestCodeJailDarkLaunch(unittest.TestCase):
# Both will attempt to read and write the 'overwrite' key.
globals_dict = {'overwrite': 'original'}
local_globals = None
remote_globals = None
def local_exec(code, globals_dict, **kwargs):
# Preserve what local exec saw
nonlocal local_globals
local_globals = copy.deepcopy(globals_dict)
globals_dict['overwrite'] = 'mock local'
def remote_exec(data):
# Preserve what remote exec saw
nonlocal remote_globals
remote_globals = copy.deepcopy(data['globals_dict'])
data['globals_dict']['overwrite'] = 'mock remote'
return (None, None)
@@ -245,6 +257,11 @@ class TestCodeJailDarkLaunch(unittest.TestCase):
)
assert results['raised'] is None
# Both arms should have only seen the original globals object, untouched
# by the other arm.
assert local_globals == {'overwrite': 'original'}
assert remote_globals == {'overwrite': 'original'}
def test_remote_runs_even_if_local_raises(self):
"""Test that remote exec runs even if local raises."""
def local_exec(code, globals_dict, **kwargs):