diff --git a/README.md b/README.md index d20e3e86f6..86960719e5 100644 --- a/README.md +++ b/README.md @@ -349,6 +349,8 @@ You can run `interpreter -y` or set `interpreter.auto_run = True` to bypass this - Watch Open Interpreter like a self-driving car, and be prepared to end the process by closing your terminal. - Consider running Open Interpreter in a restricted environment like Google Colab or Replit. These environments are more isolated, reducing the risks of executing arbitrary code. +There is **experimental** support for a [safe mode](./docs/SAFE_MODE.md) to help mitigate some risks. + ## How Does it Work? Open Interpreter equips a [function-calling language model](https://platform.openai.com/docs/guides/gpt/function-calling) with an `exec()` function, which accepts a `language` (like "Python" or "JavaScript") and `code` to run. diff --git a/docs/SAFE_MODE.md b/docs/SAFE_MODE.md new file mode 100644 index 0000000000..85a497a304 --- /dev/null +++ b/docs/SAFE_MODE.md @@ -0,0 +1,61 @@ +# Safe Mode + +**⚠️ Safe mode is experimental and does not provide any guarantees of safety or security.** + +Open Interpreter is working on providing an experimental safety toolkit to help you feel more confident running the code generated by Open Interpreter. + + +Install Open Interpreter with the safety toolkit dependencies as part of the bundle: + +```shell +pip install open-interpreter[safe] +``` + +Alternatively, you can install the safety toolkit dependencies separately in your virtual environment: + +```shell +pip install semgrep +``` + +## Features + +- **No Auto Run**: Safe mode disables the ability to automatically execute code +- **Code Scanning**: Scan generated code for vulnerabilities with [`semgrep`](https://semgrep.dev/) + +## Enabling Safe Mode + +You can enable safe mode by passing the `--safe` flag when invoking `interpreter` or by configuring `safe_mode` in your [config file](https://github.com/KillianLucas/open-interpreter#configuration). + +The safe mode setting has three options: + +- `off`: disables the safety toolkit (_default_) +- `ask`: prompts you to confirm that you want to scan code +- `auto`: automatically scans code + +### Example Config: + +```yaml +model: gpt-4 +temperature: 0 +debug_mode: false +safe_mode: ask +``` + +## Roadmap + +Some upcoming features that enable even more safety: + +- [Execute code in containers](https://github.com/KillianLucas/open-interpreter/pull/459) + +## Tips & Tricks + +You can adjust the `system_message` in your [config file](https://github.com/KillianLucas/open-interpreter#configuration) to include instructions for the model to scan packages with [`guarddog`]() before installing them. + +```yaml +model: gpt-4 +debug_mode: false +safe_mode: ask +system_message: | + # normal system message here + BEFORE INSTALLING ANY PACKAGES WITH pip OR npm YOU MUST SCAN THEM WITH `guarddog` FIRST. Run `guarddog pypi scan $package` for pip packages and `guarddog npm scan $package` for npm packages. `guarddog` only accepts one package name at a time. +``` \ No newline at end of file diff --git a/interpreter/terminal_interface/terminal_interface.py b/interpreter/terminal_interface/terminal_interface.py index a65b3d63cc..390240dbb5 100644 --- a/interpreter/terminal_interface/terminal_interface.py +++ b/interpreter/terminal_interface/terminal_interface.py @@ -9,6 +9,7 @@ from ..utils.display_markdown_message import display_markdown_message from ..utils.truncate_output import truncate_output from ..utils.scan_code import scan_code +from ..utils.check_for_package import check_for_package def terminal_interface(interpreter, message): @@ -17,8 +18,9 @@ def terminal_interface(interpreter, message): "**Open Interpreter** will require approval before running code." ] - if interpreter.safe_mode != "off": - interpreter_intro_message.append(f"**Safe Mode**: {interpreter.safe_mode}\n\n>Note: **Safe Mode** requires `semgrep` (`pip install semgrep`)") + if interpreter.safe_mode == "ask" or interpreter.safe_mode == "auto": + if not check_for_package("semgrep"): + interpreter_intro_message.append(f"**Safe Mode**: {interpreter.safe_mode}\n\n>Note: **Safe Mode** requires `semgrep` (`pip install semgrep`)") else: interpreter_intro_message.append( "Use `interpreter -y` to bypass this." diff --git a/interpreter/utils/check_for_package.py b/interpreter/utils/check_for_package.py new file mode 100644 index 0000000000..159bb37346 --- /dev/null +++ b/interpreter/utils/check_for_package.py @@ -0,0 +1,19 @@ +import importlib.util +import sys + +#borrowed from: https://stackoverflow.com/a/1051266/656011 +def check_for_package(package): + if package in sys.modules: + return True + elif (spec := importlib.util.find_spec(package)) is not None: + try: + module = importlib.util.module_from_spec(spec) + + sys.modules[package] = module + spec.loader.exec_module(module) + + return True + except ImportError: + return False + else: + return False \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index b7b908b9f8..4d0f46de3a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2641,7 +2641,10 @@ files = [ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] +[extras] +safe = [] + [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "2ea4e2d34f63c6d07bbf5adcc477ab74cb6991270c1f319a45ce2c7a209459a1" +content-hash = "f370ffc37f124bcd3eed9149d42712d9f588067d5a446eba54956cc508afa9f5" diff --git a/pyproject.toml b/pyproject.toml index 6123fe61c1..63b62dad73 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,3 +46,6 @@ build-backend = "poetry.core.masonry.api" [tool.poetry.scripts] interpreter = "interpreter:cli" + +[tool.poetry.extras] +safe = ["semgrep"] \ No newline at end of file