Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## v0.2.4 (2025-05-22)

### 🐛🚑️ Fixes

- **versioning**: minor version update

### ✅🤡🧪 Tests

- **testing**: increased coverage for testings up to 55%

### 📌➕⬇️➖⬆️ Dependencies

- **commitizen**: minor fixes

## v0.2.3 (2025-05-21)

### 🐛🚑️ Fixes
Expand Down
6 changes: 3 additions & 3 deletions hackagent/attacks/AdvPrefix/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"output_dir": "./logs/runs",
# --- Model Configurations ---
"generator": {
"identifier": "ollama/llama2-uncensored",
"identifier": "hackagent/generate",
"endpoint": "https://hackagent.dev/api/generate",
"batch_size": 2,
"max_new_tokens": 50,
Expand All @@ -15,14 +15,14 @@
},
"judges": [
{
"identifier": "ollama/llama3",
"identifier": "hackagent/judge",
"endpoint": "https://hackagent.dev/api/judge",
"type": "harmbench",
}
],
"selection_judges": [
{
"identifier": "ollama/llama3",
"identifier": "hackagent/judge",
"endpoint": "https://hackagent.dev/api/judge",
"type": "harmbench",
}
Expand Down
23 changes: 0 additions & 23 deletions hackagent/attacks/AdvPrefix/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,7 @@ def _construct_prompts(
if n_samples <= 0:
continue

# chat = [{"role": "user", "content": goal}] # Not directly used for router prompt format
try:
# The prompt for the router will be the fully constructed context.
# Custom chat templating needs to happen before sending to router.
# This templating logic might be simplified if direct calls are made,
# as the local proxy expects a more direct LiteLLM-like payload.

# For direct calls, the "prompt" is often just the user message content.
# For AgentRouter, the current logic constructs a more complex prompt string.
# We will adapt this based on whether we're calling directly or via router.

# The `final_prompt` here is what's sent to LiteLLM or the router.
# For direct local proxy, `messages` will be constructed later.
# For AgentRouter, this `final_prompt` is used.

# Let's keep final_prompt simple for now, it's the content for the "user" role
# and meta_prefix will be added to the generated part.
# This part of the logic might need to be revisited based on how CustomChatTemplates are meant to work
# with local proxy vs router.

# The current _construct_prompts prepares a `final_prompt` string.
# Let's assume this `final_prompt` is the "content" for the "user" message
# when making direct calls.

if meta_prefix in CUSTOM_CHAT_TEMPLATES:
prompt_content_for_template = CUSTOM_CHAT_TEMPLATES[
meta_prefix
Expand Down
78 changes: 38 additions & 40 deletions hackagent/attacks/AdvPrefix/scorer_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,46 +77,34 @@
self.underlying_httpx_client = self.client.get_httpx_client()

self.is_local_judge_proxy_defined = False
self.actual_api_key: Optional[str] = None
self.actual_api_key: str = client.token

Check warning on line 80 in hackagent/attacks/AdvPrefix/scorer_parser.py

View check run for this annotation

Codecov / codecov/patch

hackagent/attacks/AdvPrefix/scorer_parser.py#L80

Added line #L80 was not covered by tests

if self.config.agent_endpoint and (
"localhost:8888/api/judge" in self.config.agent_endpoint
or "127.0.0.1:8888/api/judge" in self.config.agent_endpoint
):
api_key_config_value = self.config.agent_metadata.get("api_key")

Check warning on line 82 in hackagent/attacks/AdvPrefix/scorer_parser.py

View check run for this annotation

Codecov / codecov/patch

hackagent/attacks/AdvPrefix/scorer_parser.py#L82

Added line #L82 was not covered by tests

if api_key_config_value:
env_key_value = os.environ.get(api_key_config_value)
if env_key_value:
self.actual_api_key = env_key_value
self.logger.info(

Check warning on line 88 in hackagent/attacks/AdvPrefix/scorer_parser.py

View check run for this annotation

Codecov / codecov/patch

hackagent/attacks/AdvPrefix/scorer_parser.py#L84-L88

Added lines #L84 - L88 were not covered by tests
f"Loaded API key for generator from environment variable: {api_key_config_value}"
)
else:
self.actual_api_key = api_key_config_value
self.logger.info(

Check warning on line 93 in hackagent/attacks/AdvPrefix/scorer_parser.py

View check run for this annotation

Codecov / codecov/patch

hackagent/attacks/AdvPrefix/scorer_parser.py#L92-L93

Added lines #L92 - L93 were not covered by tests
f"Using provided value directly as API key for generator (not found as env var: {api_key_config_value[:5]}...)."
)

print("config.agent_endpoint", self.config.agent_endpoint)
is_local_proxy_defined = bool(

Check warning on line 98 in hackagent/attacks/AdvPrefix/scorer_parser.py

View check run for this annotation

Codecov / codecov/patch

hackagent/attacks/AdvPrefix/scorer_parser.py#L97-L98

Added lines #L97 - L98 were not covered by tests
self.config.agent_endpoint == "https://hackagent.dev/api/judge"
)

if is_local_proxy_defined:

Check warning on line 102 in hackagent/attacks/AdvPrefix/scorer_parser.py

View check run for this annotation

Codecov / codecov/patch

hackagent/attacks/AdvPrefix/scorer_parser.py#L102

Added line #L102 was not covered by tests
self.is_local_judge_proxy_defined = True
self.logger.info(
f"Local judge proxy detected for '{self.config.agent_name}' at: {self.config.agent_endpoint}"
)

if self.config.agent_metadata:
direct_api_key = self.config.agent_metadata.get("api_key")
api_key_env_var = self.config.agent_metadata.get("api_key_env_var")

if direct_api_key:
self.actual_api_key = direct_api_key
self.logger.info(
f"Using direct API key for local judge proxy '{self.config.agent_name}'."
)
elif api_key_env_var:
env_key_value = os.environ.get(api_key_env_var)
if env_key_value:
self.actual_api_key = env_key_value
self.logger.info(
f"Loaded API key for local judge proxy '{self.config.agent_name}' from env var: {api_key_env_var}"
)
else:
self.logger.warning(
f"Env var {api_key_env_var} for local judge proxy '{self.config.agent_name}' API key not found."
)
else:
self.logger.warning(
f"Local judge proxy '{self.config.agent_name}' detected, but no 'api_key' or 'api_key_env_var' found in agent_metadata."
)
else:
self.logger.warning(
f"Local judge proxy '{self.config.agent_name}' detected, but agent_metadata is missing for API key."
)

if not self.actual_api_key:
self.is_local_judge_proxy_defined = (
False # Cannot use local proxy without API key
Expand Down Expand Up @@ -497,8 +485,12 @@
super().__init__(client, config)
if not self.config.model_id: # Ensure model_id is present
raise ValueError("NuancedEvaluator requires a model_id in the config.")
if not self.agent_router or not self.agent_registration_key:
raise RuntimeError("AgentRouter not initialized for NuancedEvaluator.")
if not (self.is_local_judge_proxy_defined and self.actual_api_key) and (

Check warning on line 488 in hackagent/attacks/AdvPrefix/scorer_parser.py

View check run for this annotation

Codecov / codecov/patch

hackagent/attacks/AdvPrefix/scorer_parser.py#L488

Added line #L488 was not covered by tests
not self.agent_router or not self.agent_registration_key
):
raise RuntimeError(

Check warning on line 491 in hackagent/attacks/AdvPrefix/scorer_parser.py

View check run for this annotation

Codecov / codecov/patch

hackagent/attacks/AdvPrefix/scorer_parser.py#L491

Added line #L491 was not covered by tests
"AgentRouter not initialized for NuancedEvaluator and local proxy not available/functional."
)

def _get_request_data_for_row(self, row: pd.Series) -> Dict[str, Any]:
prompt_content = self.PROMPT.format(
Expand Down Expand Up @@ -630,9 +622,11 @@
raise ValueError(
"JailbreakBenchEvaluator requires a model_id in the config."
)
if not self.agent_router or not self.agent_registration_key:
if not (self.is_local_judge_proxy_defined and self.actual_api_key) and (

Check warning on line 625 in hackagent/attacks/AdvPrefix/scorer_parser.py

View check run for this annotation

Codecov / codecov/patch

hackagent/attacks/AdvPrefix/scorer_parser.py#L625

Added line #L625 was not covered by tests
not self.agent_router or not self.agent_registration_key
):
raise RuntimeError(
"AgentRouter not initialized for JailbreakBenchEvaluator."
"AgentRouter not initialized for JailbreakBenchEvaluator and local proxy not available/functional."
)

def _get_request_data_for_row(self, row: pd.Series) -> Dict[str, Any]:
Expand Down Expand Up @@ -732,8 +726,12 @@
)
# Depending on strictness, could raise ValueError here
# raise ValueError("HarmBenchEvaluator requires a model_id in the config.")
if not self.agent_router or not self.agent_registration_key:
raise RuntimeError("AgentRouter not initialized for HarmBenchEvaluator.")
if not (self.is_local_judge_proxy_defined and self.actual_api_key) and (

Check warning on line 729 in hackagent/attacks/AdvPrefix/scorer_parser.py

View check run for this annotation

Codecov / codecov/patch

hackagent/attacks/AdvPrefix/scorer_parser.py#L729

Added line #L729 was not covered by tests
not self.agent_router or not self.agent_registration_key
):
raise RuntimeError(

Check warning on line 732 in hackagent/attacks/AdvPrefix/scorer_parser.py

View check run for this annotation

Codecov / codecov/patch

hackagent/attacks/AdvPrefix/scorer_parser.py#L732

Added line #L732 was not covered by tests
"AgentRouter not initialized for HarmBenchEvaluator and local proxy not available/functional."
)

# model_id processing (like adding provider prefix) should ideally happen when creating
# the EvaluatorConfig instance before passing it here, or handled by the LiteLLMAgentAdapter itself.
Expand Down
2 changes: 1 addition & 1 deletion hackagent/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


def setup_package_logging(
logger_name: str = "hackagent", default_level_str: str = "INFO"
logger_name: str = "hackagent", default_level_str: str = "WARNING"
):
"""Configures RichHandler for the specified logger if not already set."""
global _rich_handler_configured_for_package
Expand Down
57 changes: 38 additions & 19 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "hackagent"
version = "0.2.3"
version = "0.2.4"
description = "HackAgent is an open-source security toolkit to detect vulnerabilities of your AI Agents."
authors = [
"Nicola Franco <nicola@vista-labs.ai>",
Expand Down Expand Up @@ -30,6 +30,8 @@ commitizen = "^4.7.1"
cz-conventional-gitmoji = "^0.7.0"
pytest-cov = "^6.1.1"
google-adk = "^0.5.0"
anyio = "^4.3.0"
pytest-asyncio = "^0.23.7"

[tool.commitizen]
name = "cz_gitmoji"
Expand Down Expand Up @@ -60,4 +62,6 @@ exclude_lines = [
]

[tool.coverage.xml]
output = "reports/coverage.xml"
output = "reports/coverage.xml"

[tool.pytest.ini_options]
Loading
Loading