Skip to content
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

[Draft] Prototype for Docker executor #225

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

aymeric-roucher
Copy link
Collaborator

@aymeric-roucher
Copy link
Collaborator Author

@stackviolator if you want to talk in more detail and have Slack we can open a colab there!

@stackviolator
Copy link
Contributor

Hey! I'll check these out. A slack collab would actually be great. In the process of disclosing a security issue to you guys, a docker executor would help remediate the issue :^)

@stackviolator
Copy link
Contributor

Ok I have some progress on my fork (main...stackviolator:smolagents:main) that is working fairly consistently for builtin tools.

Major design differences:

  • Made the containers ephemeral. A new container is spun and destroyed for each code step. This was made in case an attacker escapes the interpreter and persists within the container, any data on the container could be accessed. E.g. RAG agent sorting through internal docs.
  • No use of a socket. Since the containers are ephemeral, there isn't a need to make a server that executes commands, can just catch stdout and stderr when the container finished its script.
  • Create a new instance of a LocalPythonInterpreter in the container prior to execution. The container will install smolagents and has access to all the builtins. I played with pickling and shipping the entire object but since tools are either functions or objects, it would be a big pain to ship them between the main process and the container.

I haven't tested yet with custom tools with the @tool decorator, doubt my solution will be able to handle it. But this should be a pretty good start.

@aymeric-roucher
Copy link
Collaborator Author

aymeric-roucher commented Jan 16, 2025

Hello @stackviolator ! Two constraints should indeed absolutely be handled

  • consistent state between steps (else our agents won't really be multi-step if they can't reuse in later steps what they've built in earlier ones)
  • being able to pass custom tools!
    The pre-existing solution built by @ErikKaum already handles the consistent state, I think what it needs is mostly the custom tool part to be more secure and easily runnable!

Also check the E2B executor, it can pass custom tools (via exporting the script using Tool.save()) and has state synchronisation between local and remote machine via pickling, I think this can be applied to remote tools to.

@stackviolator
Copy link
Contributor

In my solution, the additional_args dict which is passed into call is sent to the container and used during execution. These are then passed into the new instance of the LocalPythonInterpreter. Correct me if I'm wrong but I believe this is the state transfer that you're talking about. At least that's what it looks like is happening with the (un)pickling in e2b.

I'm also a bit hesitant to keep a single container running throughout the lifetime of an agent. If an attacker can persist on the container during execution, various artifacts (API keys, previous code, data in the prompts) will likely pile up and defeat the purpose of having the sandbox in the first place. The idea behind the ephemeral containers was to emulate something like AWS Lambda.

As for the custom tools -- yes need to support those. I'll look into how you guys are doing them for e2b and Erik's implementation :)

@albertvillanova albertvillanova marked this pull request as draft January 24, 2025 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants