-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
feat: add semgrep code scanning via -safe argument #484
feat: add semgrep code scanning via -safe argument #484
Conversation
from .languages.r import R | ||
|
||
|
||
language_map = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up needing to reference the same language map that the create_code_interpreter
module was using, so I moved it into it's own module to make it easier to share.
@@ -4,6 +4,8 @@ | |||
import re | |||
|
|||
class Python(SubprocessCodeInterpreter): | |||
file_extension = "py" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These file_extension
s aren't strictly necessary, but it felt nicer when generating the temporary file for semgrep to scan to do it with the appropriate extension and could come in handy for some future ideas - like adding some functionality to directly export generated code into a file via a some %magic
command without needing to have another exchange with Open Interpreter to get it to create some code to pipe the other code into the file.
In the case of something like the JavaScript language configuration this could get a little more complicated since they could also be modules that use the mjs
extension, but for the purposes it's being used for right now - a naive extension suffices.
bd4c47a
to
96d3a85
Compare
82e5839
to
5c7e804
Compare
NOTE: This depends on #511 to work as expected. |
@ericrallen this is brilliantly, beautifully done. To me this is a strong foundation for a I'm in favor of fewer, simpler options so I'm going to remove the tiers. Just to confirm before merging this (and #511), users don't have to log in to semgrep to use it? |
@KillianLucas I've cleaned this one up a bit given the desire to put safety tools under a single flag in the future - I've also simplified the output and made I moved the temporary file creation and cleanup into it's own utility since there are other safety tools, like scanning for exposed secrets, that will likely need to leverage a similar temporary file functionality. Semgrep's free tier works really well for this usecase - just scanning a snippet of code locally - but the CLI also allows users who have a Semgrep account to login and leverage some of the more advanced features if they want. Here's some recordings of the output for each value of the flag: Open Interpreter with
|
Here are the prompts I've been using to quickly test this functionality: Generate Safe (hopefully) Code
Generate Vulnerable Code
Without the bit about testing the code scanner, sometimes it will start to argue with you about generating vulnerable code. |
You can also save the following snippets to files on your machine and ask Open Interpreter to read and execute the code. Note: These examples were generated by Open Interpreter as examples of vulnerable code that should be identified by the code scanner. JavaScriptconst vm = require('vm');
const contextObject = { globalVar: 1 };
// safe
vm.runInContext('globalVar *= 2;', contextObject);
// vulnerable
let userInput = 'this.constructor.constructor("return process.env")()'; // Value supplied by user input
vm.runInContext(`globalVar = ${userInput};`, contextObject);
// safe
const code = `return 'hello ' + name`
vm.compileFunction(code, [], { parsingContext: vm.createContext({ name: 'name' }) })
// vulnerable
let userInput = '1; while (true) Pythonimport subprocess
import sys
# Vulnerable
user_input = "foo && cat /etc/passwd" # value supplied by user
subprocess.call("grep -R {} .".format(user_input), shell=True)
# Vulnerable
user_input = "cat /etc/passwd" # value supplied by user
subprocess.run(["bash", "-c", user_input], shell=True)
# Not vulnerable
user_input = "cat /etc/passwd" # value supplied by user
subprocess.Popen(['ls', '-l', user_input])
# Not vulnerable
subprocess.check_output('ls -l dir/') |
4010999
to
313dbd4
Compare
@KillianLucas I rebased this branch, fixed a bit of code that I forgot to update from This used to display the Loading IndicatorAlso here's a simple prompt for anyone who wants to test this to get right into a state where you can test the scanner after running with
|
@@ -4,6 +4,9 @@ | |||
import re | |||
|
|||
class Python(SubprocessCodeInterpreter): | |||
file_extension = "py" | |||
proper_name = "Python" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These proper names are mostly just being used for the code scanner to say
Code Scanner: No Issues were found with this Python code
We could just rely on the lowercase language string from the code block, but it felt nicer and more human-readable this way.
interpreter_intro_message.append(f"**Safe Mode**: {interpreter.safe_mode}") | ||
else: | ||
interpreter_intro_message.append( | ||
"Use `interpreter -y` or set `auto_run: true` to bypass this." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since safe_mode
is opt-in and disables auto_run
it seemed unnecessary to mention the -y
flag.
Not sure why the workflow tests are failing. Everything seems to work when I run the test suite locally. |
@KillianLucas I’ll rebase again tomorrow to resolve the Any guidance on getting it ready to merge would be appreciated. |
This reintroduces the --safe functionality from OpenInterpreter#24. --safe has 3 possible values auto, ask, and off Code scanning is opt-in.
This is being removed from this PR in favor of a standalone fix in OpenInterpreter#511
Also update scan_code to safe_mode in conditional
8bedd4e
to
0b73235
Compare
GREAT WORK ERIC! Literally our most impressive and extensive PR on this whole project to date. Extreme utility here, and you've opened the door to a substantial wing of the OI project (and maybe even to an industry/discipline??) focused on making LLM-written code safe. Merging now. 🎉 |
Describe the changes you have made:
This PR introduces the first tool in a safety toolkit to help verify that code might be safe to execute.
It adds a
-safe
argument that can be used to enable code scanning via semgrep.-safe
has 3 possible values:off
: (default) don't enabledsafe_mode
auto
: enablesafe_mode
and always scan code withsemgrep
before asking to executeask
: enablesafe_mode
and ask the user if they want to scan a code snippet withsemgrep
before asking to executeNote: The
-safe
option is disabled by default and is entirely opt-in. Enablingsafe_mode
disablesauto_run
.Reference any relevant issue (Replaces #24)
I have tested the code on the following OS:
AI Language Model (if applicable)
I tested this with code generated and read from the filesystem with
gpt-3.5-turbo
andgpt-4
, but the code scanning doesn't include the model in any way, so it should function regardless of what model the user has configured.