Skip to content

Commit ac7ff05

Browse files
[pentest] pentest OpenAI
1 parent ca996c4 commit ac7ff05

File tree

6 files changed

+79
-15
lines changed

6 files changed

+79
-15
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,32 @@ Test the capabilities of ZenGuard AI in our ZenGuard [Playground](https://consol
3737

3838
A more detailed documentation is available at [docs.zenguard.ai](https://docs.zenguard.ai/).
3939

40+
41+
# Pentesting
42+
43+
You can run pentest against both ZenGuard AI and (optionally) ChatGPT.
44+
45+
Clone this repo and install requirements.
46+
47+
Run pentest against ZenGuard AI:
48+
49+
```shell
50+
export ZEN_API_KEY=your-api-key
51+
python tests/pentest.py
52+
```
53+
54+
Run pentest against both ZenGuard AI and ChatGPT:
55+
```shell
56+
export ZEN_API_KEY=your-api-key
57+
export OPENAI_API_KEY=your-openai-api-key
58+
python tests/pentest.py
59+
```
60+
61+
62+
Note that we always are running the pentest against the most up-to-date model. Currently, `gpt-4-0125-preview`
63+
64+
65+
4066
# Support and Contact
4167

4268
[Book a Demo](https://calendly.com/galym-u) or just shoot us an email to hello@zenguard.ai.

pyproject.toml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
[tool.poetry]
22
name = "zenguard"
3-
version = "0.1.3"
3+
version = "0.1.7"
44
description = "Plug-and-play production grade security for GenAI applications"
55
authors = ["ZenGuard Team <hello@zenguard.ai>"]
66
license = "MIT"
77
readme = "README.md"
88

99
[tool.poetry.dependencies]
1010
python = "^3.9"
11-
httpx = "^0.27.0"
11+
httpx = ">=0.24.0,<1.0.0"
1212
tqdm = "^4.66.2"
13-
14-
15-
[tool.poetry.group.pentest.dependencies]
1613
openai = "^1.14.2"
1714
rapidfuzz = "^3.7.0"
1815
pandas = "^2.2.1"

tests/pentest.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,28 @@
11
import os
22

3-
from zenguard import Credentials, Detector, Endpoint, ZenGuard, ZenGuardConfig
3+
from zenguard import (
4+
Credentials,
5+
Detector,
6+
Endpoint,
7+
SupportedLLMs,
8+
ZenGuard,
9+
ZenGuardConfig,
10+
)
411

512
if __name__ == "__main__":
613
api_key = os.environ.get("ZEN_API_KEY")
714
if not api_key:
815
raise ValueError("ZEN_API_KEY is not set")
16+
openai_api_key = os.environ.get("OPENAI_API_KEY")
17+
if not openai_api_key:
18+
print("Pentesting ZenGuard only (OpenAI API key not set)")
19+
920
config = ZenGuardConfig(credentials=Credentials(api_key=api_key))
21+
if openai_api_key:
22+
config.credentials.llm_api_key = openai_api_key
23+
config.llm = SupportedLLMs.CHATGPT
1024
zenguard = ZenGuard(config=config)
11-
zenguard.pentest(endpoint=Endpoint.ZENGUARD, detector=Detector.PROMPT_INJECTION)
25+
zenguard.pentest(endpoint=Endpoint.ZENGUARD, detector=Detector.PROMPT_INJECTION)
26+
27+
if openai_api_key:
28+
zenguard.pentest(endpoint=Endpoint.OPENAI, detector=Detector.PROMPT_INJECTION)

zenguard/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from zenguard.zenguard import ZenGuard, ZenGuardConfig, Credentials, Detector, Endpoint
1+
from zenguard.zenguard import ZenGuard, ZenGuardConfig, Credentials, Detector, Endpoint, SupportedLLMs

zenguard/pentest/prompt_injections/run.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import openai
21
from tqdm import tqdm
32

43

5-
def run_prompts_api(built_prompts, quiet=False, dry_run=False):
4+
def run_prompts_api(built_prompts, client, quiet=False, dry_run=False):
65
if not quiet:
76
built_prompts = tqdm(built_prompts)
87
for prompt in built_prompts:
98
if dry_run:
109
api_result = _get_mocked_api_response()
1110
prompt["result"] = api_result["choices"][0]["message"]["content"]
1211
else:
13-
api_result = _prompt_model_api(prompt)
12+
api_result = _prompt_model_api(prompt, client)
1413
prompt["result"] = api_result.choices[0].message.content
1514
print(prompt["result"])
1615

@@ -32,7 +31,7 @@ def _get_mocked_api_response():
3231
}
3332

3433

35-
def _prompt_model_api(prompt, use_stop=False):
34+
def _prompt_model_api(prompt, client, use_stop=False):
3635
prompt_settings = prompt["settings"]
3736

3837
api_prompt_string = prompt["prompt"]
@@ -45,7 +44,7 @@ def _prompt_model_api(prompt, use_stop=False):
4544

4645
messages = [{"role": "user", "content": api_prompt_string}]
4746

48-
response = openai.chat.completions.create(
47+
response = client.chat.completions.create(
4948
model=api_config_model,
5049
messages=messages,
5150
temperature=api_config_temperature,

zenguard/zenguard.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,35 @@
44

55
from dataclasses import dataclass
66
from enum import Enum
7+
from typing import Optional
78

89
import httpx
10+
from openai import OpenAI
911
from tqdm import tqdm
1012

11-
from zenguard.pentest.prompt_injections import config, prompting, scoring, visualization
13+
from zenguard.pentest.prompt_injections import (
14+
config,
15+
prompting,
16+
run,
17+
scoring,
18+
visualization,
19+
)
20+
21+
22+
class SupportedLLMs:
23+
CHATGPT = "chatgpt"
1224

1325

1426
@dataclass
1527
class Credentials:
1628
api_key: str
29+
llm_api_key: Optional[str] = None
1730

1831

1932
@dataclass
2033
class ZenGuardConfig:
2134
credentials: Credentials
35+
llm: Optional[SupportedLLMs] = None
2236

2337

2438
class Detector(Enum):
@@ -29,11 +43,11 @@ class Detector(Enum):
2943
KEYWORDS = "v1/detect/keywords"
3044
SECRETS = "v1/detect/secrets"
3145

46+
3247
class Endpoint(Enum):
3348
ZENGUARD = "zenguard"
3449
OPENAI = "openai"
3550

36-
3751
class ZenGuard:
3852
"""
3953
ZenGuard is a class that represents the ZenGuard object.
@@ -47,6 +61,14 @@ def __init__(
4761
self._api_key = config.credentials.api_key
4862
self._backend = "https://api.zenguard.ai/"
4963

64+
self._llm_client = None
65+
if config.llm == SupportedLLMs.CHATGPT:
66+
self._llm_client = OpenAI(
67+
api_key=config.credentials.llm_api_key,
68+
)
69+
elif config.llm is not None:
70+
raise ValueError(f"LLM {config.llm} is not supported")
71+
5072
def detect(self, detectors: list[Detector], prompt: str):
5173
if len(detectors) == 0:
5274
return {"error": "No detectors were provided"}
@@ -83,6 +105,9 @@ def pentest(self, endpoint: Endpoint, detector: Detector = None):
83105
detector == Detector.PROMPT_INJECTION
84106
), "Only prompt injection pentesting is currently supported"
85107
self._attack_zenguard(Detector.PROMPT_INJECTION, attack_prompts)
108+
elif endpoint == Endpoint.OPENAI:
109+
print("Running attack on OpenAI endpoint")
110+
run.run_prompts_api(attack_prompts, self._llm_client)
86111

87112
scoring.score_attacks(attack_prompts)
88113
df = visualization.build_dataframe(attack_prompts)

0 commit comments

Comments
 (0)