breachbench 1.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- app/__init__.py +1 -0
- app/main.py +170 -0
- breachbench/__init__.py +7 -0
- breachbench/__main__.py +6 -0
- breachbench/agent_eval.py +512 -0
- breachbench/cli.py +487 -0
- breachbench/code_scanner.py +273 -0
- breachbench/engine.py +606 -0
- breachbench/malware_scanner.py +239 -0
- breachbench/multi_machine.py +195 -0
- breachbench/shield.py +570 -0
- breachbench-1.3.1.dist-info/METADATA +541 -0
- breachbench-1.3.1.dist-info/RECORD +35 -0
- breachbench-1.3.1.dist-info/WHEEL +5 -0
- breachbench-1.3.1.dist-info/entry_points.txt +2 -0
- breachbench-1.3.1.dist-info/licenses/LICENSE +21 -0
- breachbench-1.3.1.dist-info/top_level.txt +5 -0
- config/__init__.py +1 -0
- config/machines.example.json +37 -0
- config/machines.json +37 -0
- data/__init__.py +1 -0
- data/agent_eval_tasks.json +260 -0
- data/api_eval.json +157 -0
- data/code_eval.json +134 -0
- data/malware_eval.json +110 -0
- data/phishing_eval.jsonl +30 -0
- data/scenarios_eval.json +155 -0
- data/schemas/__init__.py +1 -0
- data/schemas/api_finding_schema.json +51 -0
- data/schemas/phishing_schema.json +101 -0
- data/schemas/scenario_schema.json +68 -0
- labs/__init__.py +0 -0
- labs/vulnerable_api/__init__.py +0 -0
- labs/vulnerable_api/app.py +368 -0
- labs/vulnerable_api/openapi.json +1030 -0
app/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""BreachBench FastAPI HTTP Service."""
|
app/main.py
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""
|
|
2
|
+
BreachBench FastAPI Service (Port 8001).
|
|
3
|
+
Exposes:
|
|
4
|
+
- GET /v1/health
|
|
5
|
+
- POST /v1/phishing/score
|
|
6
|
+
- POST /v1/code/scan
|
|
7
|
+
- POST /v1/malware/scan
|
|
8
|
+
- POST /v1/agent/eval
|
|
9
|
+
- POST /v1/surface/analyze
|
|
10
|
+
- GET /v1/scenarios
|
|
11
|
+
- POST /v1/scenario/walk
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import Any, Dict, List, Optional
|
|
16
|
+
|
|
17
|
+
from fastapi import FastAPI, HTTPException
|
|
18
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
19
|
+
from pydantic import BaseModel, Field
|
|
20
|
+
|
|
21
|
+
from breachbench import __version__
|
|
22
|
+
from breachbench.agent_eval import evaluate_agent
|
|
23
|
+
from breachbench.code_scanner import scan_code_snippet
|
|
24
|
+
from breachbench.engine import (
|
|
25
|
+
analyze_api_surface,
|
|
26
|
+
score_phishing_email,
|
|
27
|
+
walk_scenario,
|
|
28
|
+
)
|
|
29
|
+
from breachbench.malware_scanner import scan_malware_payload
|
|
30
|
+
|
|
31
|
+
app = FastAPI(
|
|
32
|
+
title="BreachBench Security Evaluation Service",
|
|
33
|
+
description="Open-source AI Agent, Guardrail Shield, Code Vulnerability, Malware, Phishing & OWASP API Top 10 evaluation service.",
|
|
34
|
+
version=__version__,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
app.add_middleware(
|
|
38
|
+
CORSMiddleware,
|
|
39
|
+
allow_origins=["http://127.0.0.1:3000", "http://localhost:3000", "http://127.0.0.1:8001"],
|
|
40
|
+
allow_methods=["GET", "POST", "OPTIONS"],
|
|
41
|
+
allow_headers=["*"],
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class AttachmentItem(BaseModel):
|
|
46
|
+
filename: str
|
|
47
|
+
content_type: Optional[str] = "application/octet-stream"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class PhishingScoreRequest(BaseModel):
|
|
51
|
+
subject: str = Field(..., description="Email subject line")
|
|
52
|
+
body: str = Field(..., description="Plaintext email body")
|
|
53
|
+
from_name: str = Field("", description="Sender display name")
|
|
54
|
+
from_address: str = Field("", description="Sender email address")
|
|
55
|
+
reply_to: str = Field("", description="Reply-To email address")
|
|
56
|
+
auth_results: List[str] = Field(default_factory=list, description="Authentication-Results headers")
|
|
57
|
+
attachments: List[AttachmentItem] = Field(default_factory=list)
|
|
58
|
+
html: str = Field("", description="Optional raw HTML body")
|
|
59
|
+
llm_backend: str = Field("heuristic", description="'heuristic' | 'ollama' | 'hf'")
|
|
60
|
+
llm_model: str = Field("qwen2.5-coder:7b", description="Model identifier when llm_backend != heuristic")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class CodeScanRequest(BaseModel):
|
|
64
|
+
code: str = Field(..., description="Source code snippet to scan for OWASP / CWE vulnerabilities")
|
|
65
|
+
filename: str = Field("<snippet>", description="Optional filename label")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class MalwareScanRequest(BaseModel):
|
|
69
|
+
content: str = Field(..., description="File content or payload string to scan for malware & supply-chain indicators")
|
|
70
|
+
filename: str = Field("<payload>", description="Optional filename (e.g. package.json, setup.py, lure.xlsm)")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class AgentEvalRequest(BaseModel):
|
|
74
|
+
provider: str = Field("deterministic", description="'deterministic' | 'openai' | 'ollama' | 'echo'")
|
|
75
|
+
model: str = Field("gpt-4.1-mini", description="Target LLM/agent model identifier")
|
|
76
|
+
base_url: Optional[str] = Field(None, description="Optional OpenAI-compatible base URL")
|
|
77
|
+
api_mode: str = Field("chat", description="'chat' (/v1/chat/completions) or 'responses' (/v1/responses)")
|
|
78
|
+
suite: str = Field("all", description="Suite filter or 'all'")
|
|
79
|
+
shield: bool = Field(False, description="Enable 3-layer BreachBench Guardrail Shield")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class SurfaceAnalyzeRequest(BaseModel):
|
|
83
|
+
openapi_spec: Optional[Dict[str, Any]] = None
|
|
84
|
+
endpoints: Optional[List[Dict[str, Any]]] = None
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class ScenarioWalkRequest(BaseModel):
|
|
88
|
+
scenario_id: Optional[str] = None
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@app.get("/v1/health")
|
|
92
|
+
def health_check() -> Dict[str, Any]:
|
|
93
|
+
return {
|
|
94
|
+
"status": "ok",
|
|
95
|
+
"service": "breachbench",
|
|
96
|
+
"version": __version__,
|
|
97
|
+
"capabilities": [
|
|
98
|
+
"phishing_bec_mfa_triage",
|
|
99
|
+
"prompt_injection_shield",
|
|
100
|
+
"guardrail_shield_3_layer",
|
|
101
|
+
"code_vulnerability_scanner_cwe_owasp",
|
|
102
|
+
"malware_and_supply_chain_scanner",
|
|
103
|
+
"ai_agent_security_evaluator",
|
|
104
|
+
"owasp_api_top10_analyzer",
|
|
105
|
+
"scenario_walker",
|
|
106
|
+
],
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@app.post("/v1/phishing/score")
|
|
111
|
+
def phishing_score_endpoint(req: PhishingScoreRequest) -> Dict[str, Any]:
|
|
112
|
+
return score_phishing_email(
|
|
113
|
+
subject=req.subject,
|
|
114
|
+
body=req.body,
|
|
115
|
+
from_name=req.from_name,
|
|
116
|
+
from_address=req.from_address,
|
|
117
|
+
reply_to=req.reply_to,
|
|
118
|
+
auth_results=req.auth_results,
|
|
119
|
+
attachments=[a.model_dump() for a in req.attachments],
|
|
120
|
+
html=req.html,
|
|
121
|
+
llm_backend=req.llm_backend,
|
|
122
|
+
llm_model=req.llm_model,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@app.post("/v1/code/scan")
|
|
127
|
+
def code_scan_endpoint(req: CodeScanRequest) -> Dict[str, Any]:
|
|
128
|
+
return scan_code_snippet(req.code, filename=req.filename)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@app.post("/v1/malware/scan")
|
|
132
|
+
def malware_scan_endpoint(req: MalwareScanRequest) -> Dict[str, Any]:
|
|
133
|
+
return scan_malware_payload(req.content, filename=req.filename)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@app.post("/v1/agent/eval")
|
|
137
|
+
def agent_eval_endpoint(req: AgentEvalRequest) -> Dict[str, Any]:
|
|
138
|
+
try:
|
|
139
|
+
return evaluate_agent(
|
|
140
|
+
provider=req.provider,
|
|
141
|
+
model=req.model,
|
|
142
|
+
base_url=req.base_url,
|
|
143
|
+
api_mode=req.api_mode,
|
|
144
|
+
suite=req.suite,
|
|
145
|
+
shield=req.shield,
|
|
146
|
+
)
|
|
147
|
+
except ValueError as exc:
|
|
148
|
+
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@app.post("/v1/surface/analyze")
|
|
152
|
+
def surface_analyze_endpoint(req: SurfaceAnalyzeRequest) -> Dict[str, Any]:
|
|
153
|
+
if req.openapi_spec:
|
|
154
|
+
return analyze_api_surface(req.openapi_spec)
|
|
155
|
+
if req.endpoints:
|
|
156
|
+
return analyze_api_surface({"endpoints": req.endpoints})
|
|
157
|
+
return analyze_api_surface()
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@app.get("/v1/scenarios")
|
|
161
|
+
def list_scenarios_endpoint() -> Dict[str, Any]:
|
|
162
|
+
return walk_scenario(None)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@app.post("/v1/scenario/walk")
|
|
166
|
+
def walk_scenario_endpoint(req: ScenarioWalkRequest) -> Dict[str, Any]:
|
|
167
|
+
try:
|
|
168
|
+
return walk_scenario(req.scenario_id)
|
|
169
|
+
except ValueError as exc:
|
|
170
|
+
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
breachbench/__init__.py
ADDED