Skip to content

Commit

Permalink
Add Codex vuln detector
Browse files Browse the repository at this point in the history
The detector requires:
- The user to use the flag `--codex` (meaning that codex is not ran by default)
- `openai` must be installed, and `OPENAI_API_KEY` set

The detector works at the contract level, and send the whole contract body to codex
  • Loading branch information
montyly committed Dec 6, 2022
1 parent 0dc2a49 commit c02231f
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 0 deletions.
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"deepdiff",
"numpy",
"solc-select>=v1.0.0b1",
"openai"
]
},
license="AGPL-3.0",
Expand Down
4 changes: 4 additions & 0 deletions slither/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,10 @@ def parse_args(

parser.add_argument("filename", help=argparse.SUPPRESS)

parser.add_argument(
"--codex", help="Enable codex (require an OpenAI API Key)", action="store_true", default=False
)

cryticparser.init(parser)

parser.add_argument(
Expand Down
1 change: 1 addition & 0 deletions slither/detectors/all_detectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,4 @@
from .statements.delegatecall_in_loop import DelegatecallInLoop
from .functions.protected_variable import ProtectedVariables
from .functions.permit_domain_signature_collision import DomainSeparatorCollision
from .functions.codex import Codex
80 changes: 80 additions & 0 deletions slither/detectors/functions/codex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import logging
import os
from typing import List

from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.utils.output import Output

logger = logging.getLogger("Slither")


class Codex(AbstractDetector):
"""
Use codex to detect vulnerability
"""

ARGUMENT = "codex"
HELP = "Use Codex to find vulnerabilities."
IMPACT = DetectorClassification.HIGH
CONFIDENCE = DetectorClassification.LOW

WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#codex"

WIKI_TITLE = "Codex"
WIKI_DESCRIPTION = "Use [codex](https://openai.com/blog/openai-codex/) to find vulnerabilities"

# region wiki_exploit_scenario
WIKI_EXPLOIT_SCENARIO = """N/A"""
# endregion wiki_exploit_scenario

WIKI_RECOMMENDATION = "Review codex's message."

def _detect(self) -> List[Output]:
results: List[Output] = []

if not self.slither.codex_enabled:
return []

try:
# pylint: disable=import-outside-toplevel
import openai
except ImportError:
logging.info("OpenAI was not installed")
logging.info('run "pip install openai"')
return []

api_key = os.getenv("OPENAI_API_KEY")
if api_key is None:
logging.info(
"Please provide an Open API Key in OPENAI_API_KEY (https://beta.openai.com/account/api-keys)"
)
return []
openai.api_key = api_key

for contract in self.compilation_unit.contracts:
prompt = "Is there a vulnerability in this solidity contracts?\n"
src_mapping = contract.source_mapping
content = contract.compilation_unit.core.source_code[src_mapping.filename.absolute]
start = src_mapping.start
end = src_mapping.start + src_mapping.length
prompt += content[start:end]
answer = openai.Completion.create( # type: ignore
model="text-davinci-003", prompt=prompt, temperature=0, max_tokens=200
)

if "choices" in answer:
if answer["choices"]:
if "text" in answer["choices"][0]:
if "Yes," in answer["choices"][0]["text"]:
info = [
"Codex detected a potential bug in ",
contract,
"\n",
answer["choices"][0]["text"],
"\n",
]

res = self.generate_result(info)
results.append(res)

return results
3 changes: 3 additions & 0 deletions slither/slither.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ def __init__(self, target: Union[str, CryticCompile], **kwargs):

self.line_prefix = kwargs.get("change_line_prefix", "#")

# Indicate if codex-related features should be used
self.codex_enabled = kwargs.get("codex", False)

self._parsers: List[SlitherCompilationUnitSolc] = []
try:
if isinstance(target, CryticCompile):
Expand Down

0 comments on commit c02231f

Please sign in to comment.