mirror of
https://github.com/msoedov/agentic_security.git
synced 2026-06-24 22:29:56 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5395c6b7a0 |
@@ -26,6 +26,7 @@
|
||||
- LLM API integration and stress testing 🛠️
|
||||
- Wide range of fuzzing and attack techniques 🌀
|
||||
|
||||
|
||||
| Tool | Source | Integrated |
|
||||
|-------------------------|-------------------------------------------------------------------------------|------------|
|
||||
| Garak | [leondz/garak](https://github.com/leondz/garak) | ✅ |
|
||||
@@ -34,8 +35,11 @@
|
||||
| Custom Huggingface Datasets | markush1/LLM-Jailbreak-Classifier | ✅ |
|
||||
| Local CSV Datasets | - | ✅ |
|
||||
|
||||
|
||||
|
||||
Note: Please be aware that Agentic Security is designed as a safety scanner tool and not a foolproof solution. It cannot guarantee complete protection against all possible threats.
|
||||
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
To get started with Agentic Security, simply install the package using pip:
|
||||
@@ -69,6 +73,7 @@ agentic_security --port=PORT --host=HOST
|
||||
|
||||
## UI 🧙
|
||||
|
||||
|
||||
<img width="100%" alt="booking-screen" src="https://res.cloudinary.com/do9qa2bqr/image/upload/v1713002396/1-ezgif.com-video-to-gif-converter_s2hsro.gif">
|
||||
|
||||
## LLM kwargs
|
||||
@@ -300,7 +305,11 @@ Agentic Security is released under the Apache License v2.
|
||||
|
||||
## Contact us
|
||||
|
||||
## 🤝 Schedule a 1-on-1 Session
|
||||
|
||||
<a href="https://cal.com/alexander-myasoedov-go2tfs/30min"><img src="https://cal.com/book-with-cal-dark.svg" alt="Book us with Cal.com"></a>
|
||||
|
||||
Book a 1-on-1 Session with the founders, to discuss any issues, provide feedback, or explore how we can improve agentic_security for you.
|
||||
|
||||
## Repo Activity
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ REGISTRY = [
|
||||
"tokens": 224196,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Hugging Face Datasets",
|
||||
"selected": False,
|
||||
"selected": True,
|
||||
"dynamic": False,
|
||||
"url": "https://huggingface.co/ShawnMenz/DAN_jailbreak",
|
||||
},
|
||||
@@ -17,7 +17,7 @@ REGISTRY = [
|
||||
"tokens": 6988,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Hugging Face Datasets",
|
||||
"selected": False,
|
||||
"selected": True,
|
||||
"dynamic": False,
|
||||
"url": "https://huggingface.co/deepset/prompt-injections",
|
||||
},
|
||||
@@ -27,7 +27,7 @@ REGISTRY = [
|
||||
"tokens": 26971,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Hugging Face Datasets",
|
||||
"selected": False,
|
||||
"selected": True,
|
||||
"dynamic": False,
|
||||
"url": "https://huggingface.co/rubend18/ChatGPT-Jailbreak-Prompts",
|
||||
},
|
||||
@@ -37,7 +37,7 @@ REGISTRY = [
|
||||
"tokens": 7172,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Hugging Face Datasets",
|
||||
"selected": False,
|
||||
"selected": True,
|
||||
"dynamic": False,
|
||||
"url": "https://huggingface.co/notrichardren/refuse-to-answer-prompts",
|
||||
},
|
||||
@@ -47,7 +47,7 @@ REGISTRY = [
|
||||
"tokens": 19758,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Hugging Face Datasets",
|
||||
"selected": False,
|
||||
"selected": True,
|
||||
"dynamic": False,
|
||||
"url": "https://huggingface.co/Lemhf14/EasyJailbreak_Datasets",
|
||||
},
|
||||
@@ -57,29 +57,9 @@ REGISTRY = [
|
||||
"tokens": 19758,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Hugging Face Datasets",
|
||||
"selected": False,
|
||||
"dynamic": False,
|
||||
"url": "https://huggingface.co/markush1/LLM-Jailbreak-Classifier",
|
||||
},
|
||||
{
|
||||
"dataset_name": "JailbreakV-28K/JailBreakV-28k",
|
||||
"num_prompts": 28300,
|
||||
"tokens": 1975800,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Hugging Face Datasets",
|
||||
"selected": True,
|
||||
"dynamic": False,
|
||||
"url": "https://huggingface.co/JailbreakV-28K/JailBreakV-28k",
|
||||
},
|
||||
{
|
||||
"dataset_name": "ShawnMenz/jailbreak_sft_rm_ds",
|
||||
"num_prompts": 371000,
|
||||
"tokens": 1975800,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Hugging Face Datasets",
|
||||
"selected": False,
|
||||
"dynamic": False,
|
||||
"url": "https://huggingface.co/ShawnMenz/jailbreak_sft_rm_ds",
|
||||
"url": "https://huggingface.co/markush1/LLM-Jailbreak-Classifier",
|
||||
},
|
||||
{
|
||||
"dataset_name": "Steganography",
|
||||
@@ -87,7 +67,7 @@ REGISTRY = [
|
||||
"tokens": 0,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Local mutation dataset",
|
||||
"selected": False,
|
||||
"selected": True,
|
||||
"dynamic": True,
|
||||
"url": "",
|
||||
},
|
||||
@@ -97,7 +77,7 @@ REGISTRY = [
|
||||
"tokens": 0,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Local mutation dataset",
|
||||
"selected": False,
|
||||
"selected": True,
|
||||
"dynamic": True,
|
||||
"url": "",
|
||||
},
|
||||
@@ -107,30 +87,10 @@ REGISTRY = [
|
||||
"tokens": 0,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Local dataset",
|
||||
"selected": False,
|
||||
"selected": True,
|
||||
"dynamic": True,
|
||||
"url": "",
|
||||
},
|
||||
{
|
||||
"dataset_name": "jailbreak_llms/2023_05_07",
|
||||
"num_prompts": 0,
|
||||
"tokens": 0,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Github",
|
||||
"selected": False,
|
||||
"dynamic": True,
|
||||
"url": "https://github.com/verazuo/jailbreak_llms",
|
||||
},
|
||||
{
|
||||
"dataset_name": "jailbreak_llms/2023_12_25.csv",
|
||||
"num_prompts": 0,
|
||||
"tokens": 0,
|
||||
"approx_cost": 0.0,
|
||||
"source": "Github",
|
||||
"selected": False,
|
||||
"dynamic": True,
|
||||
"url": "https://github.com/verazuo/jailbreak_llms",
|
||||
},
|
||||
{
|
||||
"dataset_name": "Malwaregen",
|
||||
"num_prompts": 0,
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import io
|
||||
import os
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
from functools import lru_cache
|
||||
|
||||
import httpx
|
||||
import pandas as pd
|
||||
from loguru import logger
|
||||
|
||||
@@ -150,44 +148,6 @@ def load_dataset_v6():
|
||||
)
|
||||
|
||||
|
||||
@cache_to_disk()
|
||||
def load_dataset_v7():
|
||||
|
||||
splits = {
|
||||
"mini_JailBreakV_28K": "JailBreakV_28K/mini_JailBreakV_28K.csv",
|
||||
"JailBreakV_28K": "JailBreakV_28K/JailBreakV_28K.csv",
|
||||
}
|
||||
df = pd.read_csv(
|
||||
"hf://datasets/JailbreakV-28K/JailBreakV-28k/" + splits["JailBreakV_28K"]
|
||||
)
|
||||
bad_prompts = df["jailbreak_query"].tolist()
|
||||
print(df.shape)
|
||||
return ProbeDataset(
|
||||
dataset_name="JailbreakV-28K/JailBreakV-28k",
|
||||
metadata={},
|
||||
prompts=bad_prompts,
|
||||
tokens=count_words_in_list(bad_prompts),
|
||||
approx_cost=0.0,
|
||||
)
|
||||
|
||||
|
||||
@cache_to_disk()
|
||||
def load_dataset_v8():
|
||||
|
||||
df = pd.read_csv(
|
||||
"hf://datasets/ShawnMenz/jailbreak_sft_rm_ds/jailbreak_sft_rm_ds.csv",
|
||||
names=["jailbreak", "prompt"],
|
||||
)
|
||||
filtered = df[df["jailbreak"] == "jailbreak"]["prompt"].tolist()
|
||||
return ProbeDataset(
|
||||
dataset_name="JailbreakV-28K/JailBreakV-28k",
|
||||
metadata={},
|
||||
prompts=filtered,
|
||||
tokens=count_words_in_list(filtered),
|
||||
approx_cost=0.0,
|
||||
)
|
||||
|
||||
|
||||
@cache_to_disk()
|
||||
def load_dataset_v5():
|
||||
from datasets import load_dataset
|
||||
@@ -213,22 +173,6 @@ def load_dataset_v5():
|
||||
)
|
||||
|
||||
|
||||
@cache_to_disk()
|
||||
def load_generic_csv(url, name, column="prompt", predicator=None):
|
||||
r = httpx.get(url)
|
||||
content = r.content
|
||||
df = pd.read_csv(io.StringIO(content.decode("utf-8")))
|
||||
logger.info(f"Loaded {len(df)} prompts from {url}")
|
||||
filtered_prompts = df[df.apply(predicator, axis=1)][column].tolist()
|
||||
return ProbeDataset(
|
||||
dataset_name=name,
|
||||
metadata={},
|
||||
prompts=filtered_prompts,
|
||||
tokens=count_words_in_list(filtered_prompts),
|
||||
approx_cost=0.0,
|
||||
)
|
||||
|
||||
|
||||
def prepare_prompts(dataset_names, budget, tools_inbox=None):
|
||||
# ## Datasets used and cleaned:
|
||||
# markush1/LLM-Jailbreak-Classifier
|
||||
@@ -244,20 +188,6 @@ def prepare_prompts(dataset_names, budget, tools_inbox=None):
|
||||
"rubend18/ChatGPT-Jailbreak-Prompts": load_dataset_v3,
|
||||
"Lemhf14/EasyJailbreak_Datasets": load_dataset_v5,
|
||||
"markush1/LLM-Jailbreak-Classifier": load_dataset_v6,
|
||||
"JailbreakV-28K/JailBreakV-28k": load_dataset_v7,
|
||||
"ShawnMenz/jailbreak_sft_rm_ds": load_dataset_v8,
|
||||
"verazuo/jailbreak_llms/2023_05_07": lambda: load_generic_csv(
|
||||
url="https://raw.githubusercontent.com/verazuo/jailbreak_llms/main/data/prompts/jailbreak_prompts_2023_05_07.csv",
|
||||
name="verazuo/jailbreak_llms/2023_05_07",
|
||||
column="prompt",
|
||||
predicator=lambda x: bool(x["jailbreak"]),
|
||||
),
|
||||
"verazuo/jailbreak_llms/2023_12_25.csv": lambda: load_generic_csv(
|
||||
url="https://raw.githubusercontent.com/verazuo/jailbreak_llms/main/data/prompts/jailbreak_prompts_2023_12_25.csv.csv",
|
||||
name="verazuo/jailbreak_llms/2023_12_25.csv",
|
||||
column="prompt",
|
||||
predicator=lambda x: bool(x["jailbreak"]),
|
||||
),
|
||||
"Custom CSV": load_local_csv,
|
||||
}
|
||||
|
||||
|
||||
@@ -143,98 +143,89 @@
|
||||
v-model="modelSpec"
|
||||
@input="adjustHeight"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="flex justify-between items-center">
|
||||
<label for="max-budget"
|
||||
class="text-sm font-medium text-gray-700">
|
||||
Maximum Budget
|
||||
</label>
|
||||
<div class="flex items-center space-x-2">
|
||||
<input
|
||||
id="budget-display"
|
||||
v-model="budget"
|
||||
@change="updateBudgetFromInput"
|
||||
class="w-20 px-2 py-1 text-right text-sm font-medium text-gray-900 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||||
type="text" />
|
||||
<span class="text-sm font-medium text-gray-600">M
|
||||
Tokens</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<input
|
||||
id="max-budget"
|
||||
v-model="budget"
|
||||
@input="updateBudgetFromSlider"
|
||||
type="range"
|
||||
min="1"
|
||||
max="100"
|
||||
step="1"
|
||||
class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
|
||||
<div
|
||||
class="absolute -top-6 left-0 w-full flex justify-between text-xs text-gray-600">
|
||||
<span>1M</span>
|
||||
<span>25M</span>
|
||||
<span>50M</span>
|
||||
<span>75M</span>
|
||||
<span>100M</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid gap-1.5">
|
||||
<label
|
||||
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
for="max-budget">
|
||||
Maximum Budget in {{budget}}M Tokens
|
||||
</label>
|
||||
<input
|
||||
class="flex h-10 w-full rounded-md border border-earth-disabled bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
id="max-budget"
|
||||
placeholder="Enter maximum budget..."
|
||||
type="number"
|
||||
v-model="budget" />
|
||||
</div>
|
||||
<div
|
||||
class="rounded-lg text-card-foreground shadow-sm mt-10 mb-10 border border-gray-300">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 mt-5 mb-5">
|
||||
<div class="flex flex-col space-y-4">
|
||||
<!-- Accordion Header -->
|
||||
<button
|
||||
@click="toggleDatasets"
|
||||
class="flex justify-between items-center text-lg font-semibold w-full py-2 text-center">
|
||||
Modules [{{selectedDS}}]
|
||||
selected
|
||||
<svg
|
||||
:class="{'rotate-180': showDatasets}"
|
||||
class="h-5 w-5 transform transition-transform duration-200"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Modules Selection -->
|
||||
<div class="border border-gray-200 rounded-md">
|
||||
<button
|
||||
@click="toggleDatasets"
|
||||
class="flex justify-between items-center w-full px-4 py-3 text-left text-gray-700 font-medium bg-gray-50 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-inset">
|
||||
<span>Modules [{{selectedDS}} selected]</span>
|
||||
<svg :class="{'rotate-180': showDatasets}"
|
||||
class="h-5 w-5 text-gray-500"
|
||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
|
||||
fill="currentColor">
|
||||
<path fill-rule="evenodd"
|
||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
<div v-show="showDatasets" class="p-4 bg-white">
|
||||
<div class="flex justify-between mb-4">
|
||||
<button
|
||||
@click="selectAllPackages"
|
||||
class="px-3 py-1 text-sm font-medium text-indigo-600 hover:text-indigo-500 focus:outline-none focus:underline">
|
||||
Select All
|
||||
</button>
|
||||
<button
|
||||
@click="deselectAllPackages"
|
||||
class="px-3 py-1 text-sm font-medium text-gray-600 hover:text-gray-500 focus:outline-none focus:underline">
|
||||
Deselect All
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
<!-- Accordion Content -->
|
||||
<div
|
||||
v-for="(package, index) in dataConfig"
|
||||
:key="index"
|
||||
@click="addPackage(index)"
|
||||
class="border rounded-md p-3 cursor-pointer transition-all hover:shadow-md"
|
||||
:class="{'border-indigo-500 bg-indigo-50': package.selected, 'border-gray-200': !package.selected}">
|
||||
<div class="font-medium"
|
||||
:class="{'text-indigo-700': package.selected, 'text-gray-900': !package.selected}">
|
||||
{{ package.dataset_name }}
|
||||
</div>
|
||||
<div class="text-sm text-gray-500 mt-1">{{ package.source
|
||||
|| 'Local dataset' }}</div>
|
||||
<div class="mt-2 text-sm font-semibold"
|
||||
:class="{'text-indigo-600': package.selected, 'text-gray-700': !package.selected}">
|
||||
{{ package.dynamic ? 'Dynamic dataset' :
|
||||
`${package.num_prompts.toLocaleString()} prompts` }}
|
||||
v-show="showDatasets"
|
||||
class="grid grid-cols-1 md:grid-cols-4 gap-4 transition-all duration-500 ">
|
||||
<div
|
||||
v-for="(package, index) in dataConfig"
|
||||
:key="index"
|
||||
@click="addPackage(index)"
|
||||
class="border-2 rounded-lg p-4 flex flex-col items-start hover:shadow-md transition-all"
|
||||
:class="{'border-earth-1': package.selected, 'border-gray-200': !package.selected}">
|
||||
<div class="flex items-center justify-between w-full">
|
||||
<div
|
||||
class="font-medium"
|
||||
:class="{'text-earth-1': package.selected, 'text-gray-800': !package.selected}">
|
||||
{{ package.dataset_name }}
|
||||
</div>
|
||||
<svg
|
||||
class="h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
:class="{'text-earth-1': package.selected, 'text-gray-600': !package.selected}">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="text-sm text-gray-600">
|
||||
{{ package.source || 'Local dataset' }}
|
||||
</div>
|
||||
<div class="mt-2 text-gray-800 font-semibold"
|
||||
v-if="!package.dynamic">
|
||||
{{ package.num_prompts.toLocaleString() }} prompts
|
||||
</div>
|
||||
<div class="mt-2 text-gray-800 font-semibold"
|
||||
v-if="package.dynamic">
|
||||
Dynamic dataset
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
|
||||
role="alert" v-if="errorMsg">
|
||||
@@ -284,7 +275,6 @@
|
||||
d="M5 12h14"></path><path
|
||||
d="m12 5 7 7-7 7"></path></svg>
|
||||
Run Scan
|
||||
<span class="sr-only">(Initiates the security scan)</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -599,35 +589,6 @@ Content-Type: application/json
|
||||
this.reportImageUrl = reader.result;
|
||||
};
|
||||
},
|
||||
selectAllPackages() {
|
||||
this.dataConfig.forEach(package => {
|
||||
package.selected = true;
|
||||
});
|
||||
this.updateSelectedDS();
|
||||
},
|
||||
|
||||
deselectAllPackages() {
|
||||
this.dataConfig.forEach(package => {
|
||||
package.selected = false;
|
||||
});
|
||||
this.updateSelectedDS();
|
||||
},
|
||||
|
||||
updateSelectedDS() {
|
||||
this.selectedDS = this.dataConfig.filter(package => package.selected).length;
|
||||
},
|
||||
updateBudgetFromSlider(event) {
|
||||
this.budget = parseInt(event.target.value);
|
||||
},
|
||||
updateBudgetFromInput(event) {
|
||||
let value = parseInt(event.target.value);
|
||||
if (isNaN(value) || value < 1) {
|
||||
value = 1;
|
||||
} else if (value > 100) {
|
||||
value = 100;
|
||||
}
|
||||
this.budget = value;
|
||||
},
|
||||
startScan: async function() {
|
||||
let payload = {
|
||||
maxBudget: this.budget,
|
||||
|
||||
Generated
+4
-4
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aiohttp"
|
||||
@@ -250,13 +250,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2024.2.2"
|
||||
version = "2024.7.4"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"},
|
||||
{file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"},
|
||||
{file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"},
|
||||
{file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "agentic_security"
|
||||
version = "0.1.7"
|
||||
version = "0.1.5"
|
||||
description = "Agentic LLM vulnerability scanner"
|
||||
authors = ["Alexander Miasoiedov <msoedov@gmail.com>"]
|
||||
maintainers = ["Alexander Miasoiedov <msoedov@gmail.com>"]
|
||||
|
||||
Reference in New Issue
Block a user