Skip to content

Commit bb91579

Browse files
authored
Merge pull request #82 from SAP/develop
Release v0.4.0
2 parents be05474 + 0f51389 commit bb91579

22 files changed

Lines changed: 2021 additions & 1367 deletions

.github/workflows/changelog-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
name: Build changelog
1818
runs-on: ubuntu-latest
1919
steps:
20-
- uses: actions/checkout@v4
20+
- uses: actions/checkout@v5
2121

2222
- name: Run Changelog CI
2323
uses: saadmk11/changelog-ci@v1.2.0

.github/workflows/installation-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
runs-on: ubuntu-latest
2121
steps:
2222
- name: Check out Git repository
23-
uses: actions/checkout@v4
23+
uses: actions/checkout@v5
2424

2525
- name: Set up Python environment
2626
uses: actions/setup-python@v5

.github/workflows/lint-backend.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020

2121
steps:
2222
- name: Check out Git repository
23-
uses: actions/checkout@v4
23+
uses: actions/checkout@v5
2424

2525
- name: Set up Python environment
2626
uses: actions/setup-python@v5

.github/workflows/lint-frontend.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222

2323
steps:
2424
- name: Check out Git repository
25-
uses: actions/checkout@v4
25+
uses: actions/checkout@v5
2626

2727
- name: Set up Node.js
2828
uses: actions/setup-node@v4

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
run:
1414
shell: bash
1515
steps:
16-
- uses: actions/checkout@v4
16+
- uses: actions/checkout@v5
1717

1818
- name: Get version number
1919
id: get-pr-number

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,20 @@ data.db.*
135135
key.txt
136136

137137
# Pentest results
138+
# textattack
138139
error.txt
139140
result_fail.txt
140141
result_success.txt
141142
summary.txt
143+
# promptmap
142144
prompt_success.txt
145+
# gptfuzz
143146
result_gptfuzz.txt
147+
# codeattack
144148
codeattack_success.txt
149+
# artprompt
145150
artprompt_success.json
151+
# garak
152+
*.report.jsonl
153+
*.hitlog.jsonl
154+
*.report.html

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
# Version: v0.4.0
2+
3+
* [#44](https://github.com/SAP/STARS/pull/44): Add Garak tool
4+
* [#72](https://github.com/SAP/STARS/pull/72): Bump deprecated from 1.2.15 to 1.2.18 in /backend-agent
5+
* [#73](https://github.com/SAP/STARS/pull/73): Bump python-dotenv from 1.0.1 to 1.1.1 in /backend-agent
6+
* [#74](https://github.com/SAP/STARS/pull/74): Bump flask from 2.3.3 to 3.1.1 in /backend-agent
7+
* [#77](https://github.com/SAP/STARS/pull/77): Bump ollama from 0.4.7 to 0.5.3 in /backend-agent
8+
* [#78](https://github.com/SAP/STARS/pull/78): Bump the js-dependencies group across 1 directory with 25 updates
9+
* [#79](https://github.com/SAP/STARS/pull/79): Update faiss-cpu requirement from ~=1.9.0 to ~=1.12.0 in /backend-agent
10+
* [#80](https://github.com/SAP/STARS/pull/80): Bump actions/checkout from 4 to 5
11+
* [#81](https://github.com/SAP/STARS/pull/81): Bump mermaid from 11.4.1 to 11.10.0 in /frontend
12+
13+
114
# Version: v0.3.1
215

316
* [#50](https://github.com/SAP/STARS/pull/50): Bump webpack-dev-server and @angular-devkit/build-angular in /frontend

backend-agent/agent.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
from gen_ai_hub.proxy.core.proxy_clients import set_proxy_version
55
from gen_ai_hub.proxy.langchain.init_models import (
66
init_llm, init_embedding_model)
7-
from langchain.agents.agent_toolkits import (
8-
create_conversational_retrieval_agent, create_retriever_tool)
7+
from langchain.agents.agent_toolkits import \
8+
create_conversational_retrieval_agent
99
from langchain.embeddings import CacheBackedEmbeddings
10-
from langchain.schema.messages import SystemMessage
1110
from langchain.storage import LocalFileStore
12-
from langchain.text_splitter import RecursiveCharacterTextSplitter
1311
from langchain_community.document_loaders import DirectoryLoader
1412
from langchain_community.vectorstores import FAISS
13+
from langchain_core.messages import SystemMessage
14+
from langchain_core.tools.retriever import create_retriever_tool
15+
from langchain_text_splitters import RecursiveCharacterTextSplitter
1516

1617

1718
# load env variables
@@ -75,7 +76,7 @@ def get_retriever(document_path: str,
7576
# https://python.langchain.com/docs/modules/data_connection/document_transformers/
7677

7778
text_splitter = RecursiveCharacterTextSplitter(
78-
chunk_size=500, chunk_overlap=0)
79+
chunk_size=500, chunk_overlap=100)
7980
docs = text_splitter.split_documents(raw_docs)
8081

8182
# Vector store
@@ -194,6 +195,7 @@ def get_retriever(document_path: str,
194195
run_pyrit, \
195196
run_codeattack, \
196197
run_artprompt, \
198+
run_garak_attack, \
197199
run_attack_suite, \
198200
get_supported_models, \
199201
use_command, \
@@ -262,6 +264,14 @@ def get_retriever(document_path: str,
262264
"artprompt" framework. Use this before using the \
263265
run_artprompt tool'
264266
)
267+
# Retriever that contains notes on how to use Garak
268+
garak_notes = get_retriever(
269+
'./data/garak',
270+
'garak_how',
271+
'Steps to take to run a pentest on a LLM using the \
272+
"garak" framework. ALWAYS run this before using the \
273+
run_garak_attack tool, because it will explain how to use the tool'
274+
)
265275
# Retriever that contains notes on how to run attack suites
266276
llm_attack_suite_notes = get_retriever(
267277
'./data/suite',
@@ -300,6 +310,8 @@ def get_retriever(document_path: str,
300310
run_codeattack,
301311
artprompt_notes,
302312
run_artprompt,
313+
garak_notes,
314+
run_garak_attack,
303315
llm_attack_suite_notes,
304316
run_attack_suite,
305317
get_supported_models

backend-agent/attack.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@
1414
OUTPUT_FILE as codeattack_out_file,
1515
start_codeattack,
1616
)
17+
from libs.garak import (
18+
OUTPUT_FILE as garak_output_file,
19+
start_dan,
20+
start_encoding,
21+
start_goodside,
22+
start_latentinjection,
23+
start_malwaregen,
24+
start_phrasing,
25+
start_promptinject,
26+
start_suffix,
27+
)
1728
from libs.gptfuzz import (
1829
OUTPUT_FILE as gptfuzz_out_file,
1930
perform_gptfuzz_attack,
@@ -145,7 +156,7 @@ def start(self) -> AttackResult:
145156
Start the attack as specified with this specification.
146157
"""
147158
with Trace(self.attack, self.spec) as t:
148-
match self.attack:
159+
match self.attack.lower():
149160
case 'promptmap':
150161
return t.trace(start_prompt_map(
151162
self.target_model,
@@ -175,12 +186,54 @@ def start(self) -> AttackResult:
175186
self.eval_model,
176187
self.parameters
177188
))
189+
case 'dan':
190+
return t.trace(start_dan(
191+
self.target_model,
192+
self.parameters
193+
))
194+
case 'encoding':
195+
return t.trace(start_encoding(
196+
self.target_model,
197+
self.parameters
198+
))
199+
case 'goodside':
200+
return t.trace(start_goodside(
201+
self.target_model,
202+
self.parameters
203+
))
204+
case 'latentinjection':
205+
return t.trace(start_latentinjection(
206+
self.target_model,
207+
self.parameters
208+
))
209+
case 'malwaregen':
210+
return t.trace(start_malwaregen(
211+
self.target_model,
212+
self.parameters
213+
))
214+
case 'phrasing':
215+
return t.trace(start_phrasing(
216+
self.target_model,
217+
self.parameters
218+
))
219+
case 'promptinject':
220+
return t.trace(start_promptinject(
221+
self.target_model,
222+
self.parameters
223+
))
224+
case 'suffix':
225+
return t.trace(start_suffix(
226+
self.target_model,
227+
self.parameters
228+
))
178229
case _:
179230
raise ValueError(f'Attack {self.attack} is not known.')
180231

181232
@property
182233
def output_file(self):
183234
if 'output_file' in self.parameters:
235+
# TODO when running attacks from garak, the output_file parameter
236+
# appends .report.jsonl at runtime
184237
return self.parameters
185238
match self.attack:
186239
case 'promptmap':
@@ -191,6 +244,11 @@ def output_file(self):
191244
return codeattack_out_file
192245
case 'artprompt':
193246
return artprompt_out_file
247+
case ('dan' | 'encoding' | 'goodside' | 'latentinjection' |
248+
'malwaregen' | 'phrasing' | 'promptinject' | 'suffix'):
249+
return garak_output_file if \
250+
garak_output_file.endswith('.report.jsonl') else \
251+
f'{garak_output_file}.report.jsonl'
194252

195253

196254
class AttackSuite():

backend-agent/cli.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,94 @@ def artprompt(args):
203203
start_spec(spec, args)
204204

205205

206+
@subcommand([arg('target_model', help='Name of the target model to attack'),
207+
arg('--output_file', '-o', help='Output file with results',
208+
default=None)])
209+
def dan(args):
210+
spec = AttackSpecification.create(
211+
'dan',
212+
args.target_model,
213+
params=vars(args))
214+
start_spec(spec, args)
215+
216+
217+
@subcommand([arg('target_model', help='Name of the target model to attack'),
218+
arg('--output_file', '-o', help='Output file with results',
219+
default=None)])
220+
def encoding(args):
221+
spec = AttackSpecification.create(
222+
'encoding',
223+
args.target_model,
224+
params=vars(args))
225+
start_spec(spec, args)
226+
227+
228+
@subcommand([arg('target_model', help='Name of the target model to attack'),
229+
arg('--output_file', '-o', help='Output file with results',
230+
default=None)])
231+
def goodside(args):
232+
spec = AttackSpecification.create(
233+
'goodside',
234+
args.target_model,
235+
params=vars(args))
236+
start_spec(spec, args)
237+
238+
239+
@subcommand([arg('target_model', help='Name of the target model to attack'),
240+
arg('--output_file', '-o', help='Output file with results',
241+
default=None)])
242+
def latentinjection(args):
243+
spec = AttackSpecification.create(
244+
'latentinjection',
245+
args.target_model,
246+
params=vars(args))
247+
start_spec(spec, args)
248+
249+
250+
@subcommand([arg('target_model', help='Name of the target model to attack'),
251+
arg('--output_file', '-o', help='Output file with results',
252+
default=None)])
253+
def malwaregen(args):
254+
spec = AttackSpecification.create(
255+
'malwaregen',
256+
args.target_model,
257+
params=vars(args))
258+
start_spec(spec, args)
259+
260+
261+
@subcommand([arg('target_model', help='Name of the target model to attack'),
262+
arg('--output_file', '-o', help='Output file with results',
263+
default=None)])
264+
def phrasing(args):
265+
spec = AttackSpecification.create(
266+
'phrasing',
267+
args.target_model,
268+
params=vars(args))
269+
start_spec(spec, args)
270+
271+
272+
@subcommand([arg('target_model', help='Name of the target model to attack'),
273+
arg('--output_file', '-o', help='Output file with results',
274+
default=None)])
275+
def promptinject(args):
276+
spec = AttackSpecification.create(
277+
'promptinject',
278+
args.target_model,
279+
params=vars(args))
280+
start_spec(spec, args)
281+
282+
283+
@subcommand([arg('target_model', help='Name of the target model to attack'),
284+
arg('--output_file', '-o', help='Output file with results',
285+
default=None)])
286+
def suffix(args):
287+
spec = AttackSpecification.create(
288+
'suffix',
289+
args.target_model,
290+
params=vars(args))
291+
start_spec(spec, args)
292+
293+
206294
@subcommand([arg('file',
207295
help='Path to the JSON file containing the attack specification.', # noqa: E501
208296
nargs='?'),

0 commit comments

Comments
 (0)