Read .py attachments instead of executing them (PythonReader.parse) - #36
Open
EvolveAegis wants to merge 1 commit into
Open
Read .py attachments instead of executing them (PythonReader.parse)#36EvolveAegis wants to merge 1 commit into
EvolveAegis wants to merge 1 commit into
Conversation
PythonReader.parse ran attachments with subprocess.run(["python", file])
during a normal file-read step, unsandboxed. Return the source text
instead, like the other readers, and treat .py as a text file in
GeneralReader.read. Corrects the read_file annotation to str (it calls
.split('.')). Adds a test that reading a .py file does not execute it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR makes
PythonReader.parsereturn the file's source as text instead of running it.The sink
At commit
c23a827f561c934ce21dd950408f7606aa4a8821(currentmainHEAD),swarm/environment/tools/reader/readers.py:277(PythonReader.parse):READER_MAP[".py"] = PythonReader()(readers.py:357). On the default GAIA graphs theFileAnalysenode auto-reads task attachments:FileAnalyse.file_analyse(swarm/environment/operations/file_analyse.py:67) callsGeneralReader.read, which callsFileReader.read_file, which dispatches toPythonReader.parse.experiments/run_gaia.py:102pulls those attachments from an operator-selected local dataset dir (args.dataset_files), so a.pyattachment is executed during a normal "read the file" step — unsandboxed, no timeout, at the agent's privileges.check=Trueonly raises after the interpreter has already run the file's side effects. The other readers parse their input; this one executes it.Changes
PythonReader.parsereturns the source text:The subprocess call and the surrounding exec-result / error branches are removed.
GeneralReader.read(readers.py:397-403) currently indexes the.pyresult as a 3-tuple (file_content[0]/[1]/[2]), so that branch has to be updated to treat the result as a plain string — otherwise a string return is indexed character-by-character and the.pyoutput formatting silently breaks. After the change it matches the existingtxt/json/etc. branch (readers.py:409):If executing
.pyattachments is genuinely intended somewhere, it should be explicit opt-in behind a real sandbox (separate process, no network,timeout=, dropped privileges), not the default for "read this file".Repro
Run against commit
c23a827f561c934ce21dd950408f7606aa4a8821:Observed output:
read_fileis annotatedfile_path: Path(readers.py:367) but callsfile_path.split(".")(readers.py:368), so it requires astr; passing aPathraisesAttributeError: 'PosixPath' object has no attribute 'split'. The annotation is worth correcting alongside this PR.After this PR,
read_filereturns the source text and/tmp/canary_*is not created.A test is included: reading a
.pywhose top level writes a marker file must not produce the marker;parsereturns the file text.Scope
This is defense-in-depth. The runner takes attachments from an operator-selected local dataset dir, so turning read-is-exec into an attack needs the operator to point the agent at an untrusted dataset/upload dir — the read-is-exec primitive itself (default-reachable, unsandboxed) is real regardless. The interpreter is hardcoded as
python(notsys.executable), so on hosts withoutpythonon PATH theFileNotFoundErroris swallowed by the existing genericexceptand nothing runs; the conda quickstart providespython, but that limits which hosts are affected.