exaai-agent 2.0.9__py3-none-any.whl → 2.1.2__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.
- {exaai_agent-2.0.9.dist-info → exaai_agent-2.1.2.dist-info}/METADATA +48 -44
- {exaai_agent-2.0.9.dist-info → exaai_agent-2.1.2.dist-info}/RECORD +26 -18
- {exaai_agent-2.0.9.dist-info → exaai_agent-2.1.2.dist-info}/WHEEL +1 -1
- exaaiagnt/interface/cli.py +52 -31
- exaaiagnt/interface/main.py +11 -1
- exaaiagnt/interface/tui.py +12 -8
- exaaiagnt/llm/llm_traffic_controller.py +5 -3
- exaaiagnt/prompts/README.md +3 -1
- exaaiagnt/prompts/auto_loader.py +31 -0
- exaaiagnt/prompts/cloud/azure_cloud_security.jinja +126 -0
- exaaiagnt/prompts/cloud/gcp_cloud_security.jinja +158 -0
- exaaiagnt/prompts/cloud/kubernetes_security.jinja +97 -0
- exaaiagnt/prompts/vulnerabilities/prompt_injection.jinja +276 -0
- exaaiagnt/runtime/tool_manager.py +12 -3
- exaaiagnt/tools/__init__.py +24 -0
- exaaiagnt/tools/executor.py +1 -1
- exaaiagnt/tools/k8s_scanner/__init__.py +29 -0
- exaaiagnt/tools/k8s_scanner/k8s_actions.py +313 -0
- exaaiagnt/tools/prompt_injection/__init__.py +26 -0
- exaaiagnt/tools/prompt_injection/prompt_injection_actions.py +638 -0
- exaaiagnt/tools/python/python_instance.py +11 -1
- exaaiagnt/tools/response_analyzer.py +5 -3
- exaaiagnt/tools/smart_fuzzer.py +5 -3
- exaaiagnt/tools/vuln_validator.py +5 -3
- {exaai_agent-2.0.9.dist-info → exaai_agent-2.1.2.dist-info}/entry_points.txt +0 -0
- {exaai_agent-2.0.9.dist-info → exaai_agent-2.1.2.dist-info}/licenses/LICENSE +0 -0
exaaiagnt/tools/__init__.py
CHANGED
|
@@ -49,6 +49,19 @@ from .vuln_validator import (
|
|
|
49
49
|
VulnerabilityReport,
|
|
50
50
|
create_vuln_report,
|
|
51
51
|
)
|
|
52
|
+
from .prompt_injection import (
|
|
53
|
+
PromptInjectionScanner,
|
|
54
|
+
scan_for_prompt_injection,
|
|
55
|
+
generate_injection_payloads,
|
|
56
|
+
analyze_llm_response,
|
|
57
|
+
detect_jailbreak_success,
|
|
58
|
+
)
|
|
59
|
+
from .k8s_scanner import (
|
|
60
|
+
K8sScanner,
|
|
61
|
+
scan_cluster,
|
|
62
|
+
check_rbac,
|
|
63
|
+
check_pod_security,
|
|
64
|
+
)
|
|
52
65
|
from .tool_prompts import (
|
|
53
66
|
get_fuzzer_prompt,
|
|
54
67
|
get_analyzer_prompt,
|
|
@@ -127,6 +140,17 @@ __all__ = [
|
|
|
127
140
|
"Severity",
|
|
128
141
|
"VulnerabilityReport",
|
|
129
142
|
"create_vuln_report",
|
|
143
|
+
# Prompt Injection Scanner
|
|
144
|
+
"PromptInjectionScanner",
|
|
145
|
+
"scan_for_prompt_injection",
|
|
146
|
+
"generate_injection_payloads",
|
|
147
|
+
"analyze_llm_response",
|
|
148
|
+
"detect_jailbreak_success",
|
|
149
|
+
# K8s Scanner
|
|
150
|
+
"K8sScanner",
|
|
151
|
+
"scan_cluster",
|
|
152
|
+
"check_rbac",
|
|
153
|
+
"check_pod_security",
|
|
130
154
|
# Tool Prompts
|
|
131
155
|
"get_fuzzer_prompt",
|
|
132
156
|
"get_analyzer_prompt",
|
exaaiagnt/tools/executor.py
CHANGED
|
@@ -65,7 +65,7 @@ async def _execute_tool_in_sandbox(tool_name: str, agent_state: Any, **kwargs: A
|
|
|
65
65
|
async with httpx.AsyncClient(trust_env=False) as client:
|
|
66
66
|
try:
|
|
67
67
|
response = await client.post(
|
|
68
|
-
request_url, json=request_data, headers=headers, timeout=
|
|
68
|
+
request_url, json=request_data, headers=headers, timeout=600.0 # 10 min max
|
|
69
69
|
)
|
|
70
70
|
response.raise_for_status()
|
|
71
71
|
response_data = response.json()
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Kubernetes Security Scanner Module.
|
|
3
|
+
|
|
4
|
+
Provides comprehensive security auditing for Kubernetes clusters:
|
|
5
|
+
- RBAC analysis (excessive permissions)
|
|
6
|
+
- Pod Security Standards (PSS) compliance
|
|
7
|
+
- Network Policy auditing
|
|
8
|
+
- Secret management checks
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from .k8s_actions import (
|
|
12
|
+
K8sScanner,
|
|
13
|
+
scan_cluster,
|
|
14
|
+
check_rbac,
|
|
15
|
+
check_pod_security,
|
|
16
|
+
CheckStatus,
|
|
17
|
+
Severity,
|
|
18
|
+
SecurityFinding,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"K8sScanner",
|
|
23
|
+
"scan_cluster",
|
|
24
|
+
"check_rbac",
|
|
25
|
+
"check_pod_security",
|
|
26
|
+
"CheckStatus",
|
|
27
|
+
"Severity",
|
|
28
|
+
"SecurityFinding",
|
|
29
|
+
]
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Kubernetes Security Scanner - Core Actions
|
|
3
|
+
|
|
4
|
+
Comprehensive security testing for Kubernetes clusters including:
|
|
5
|
+
- RBAC analysis (excessive permissions)
|
|
6
|
+
- Pod Security Standards (PSS) compliance
|
|
7
|
+
- Network Policy auditing
|
|
8
|
+
- Secret management checks
|
|
9
|
+
- API Server configuration review
|
|
10
|
+
- Container vulnerability scanning integration
|
|
11
|
+
|
|
12
|
+
Author: ALhilali
|
|
13
|
+
Version: 1.0.0
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import json
|
|
18
|
+
import subprocess
|
|
19
|
+
from dataclasses import dataclass, field
|
|
20
|
+
from enum import Enum
|
|
21
|
+
from typing import List, Dict, Any, Optional
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class CheckStatus(Enum):
|
|
27
|
+
"""Status of a security check."""
|
|
28
|
+
PASS = "PASS"
|
|
29
|
+
FAIL = "FAIL"
|
|
30
|
+
WARN = "WARN"
|
|
31
|
+
ERROR = "ERROR"
|
|
32
|
+
SKIP = "SKIP"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Severity(Enum):
|
|
36
|
+
"""Severity of a finding."""
|
|
37
|
+
CRITICAL = "CRITICAL"
|
|
38
|
+
HIGH = "HIGH"
|
|
39
|
+
MEDIUM = "MEDIUM"
|
|
40
|
+
LOW = "LOW"
|
|
41
|
+
INFO = "INFO"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class SecurityFinding:
|
|
46
|
+
"""Represents a security finding in the cluster."""
|
|
47
|
+
check_id: str
|
|
48
|
+
title: str
|
|
49
|
+
description: str
|
|
50
|
+
severity: Severity
|
|
51
|
+
resource_kind: str
|
|
52
|
+
resource_name: str
|
|
53
|
+
namespace: str
|
|
54
|
+
remediation: str
|
|
55
|
+
status: CheckStatus = CheckStatus.FAIL
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class K8sScanner:
|
|
59
|
+
"""
|
|
60
|
+
Kubernetes Security Scanner.
|
|
61
|
+
Uses kubectl and specialized logic to audit cluster security.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
def __init__(self, context: Optional[str] = None, verbose: bool = False):
|
|
65
|
+
self.context = context
|
|
66
|
+
self.verbose = verbose
|
|
67
|
+
self.findings: List[SecurityFinding] = []
|
|
68
|
+
self._check_kubectl_availability()
|
|
69
|
+
|
|
70
|
+
def _check_kubectl_availability(self):
|
|
71
|
+
"""Ensure kubectl is installed and accessible."""
|
|
72
|
+
try:
|
|
73
|
+
subprocess.run(["kubectl", "version", "--client"], capture_output=True, check=True)
|
|
74
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
75
|
+
logger.warning("kubectl not found. Some checks may fail.")
|
|
76
|
+
|
|
77
|
+
def _run_kubectl(self, args: List[str]) -> Dict[str, Any]:
|
|
78
|
+
"""Run a kubectl command and return JSON output."""
|
|
79
|
+
cmd = ["kubectl"] + args + ["-o", "json"]
|
|
80
|
+
if self.context:
|
|
81
|
+
cmd.extend(["--context", self.context])
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
85
|
+
return json.loads(result.stdout)
|
|
86
|
+
except subprocess.CalledProcessError as e:
|
|
87
|
+
logger.error(f"kubectl command failed: {e.stderr}")
|
|
88
|
+
return {}
|
|
89
|
+
except json.JSONDecodeError:
|
|
90
|
+
logger.error("Failed to decode kubectl output")
|
|
91
|
+
return {}
|
|
92
|
+
|
|
93
|
+
def scan(self, namespaces: Optional[List[str]] = None) -> List[SecurityFinding]:
|
|
94
|
+
"""Run all enabled security checks."""
|
|
95
|
+
target_ns = namespaces or self._get_all_namespaces()
|
|
96
|
+
|
|
97
|
+
logger.info(f"Scanning namespaces: {target_ns}")
|
|
98
|
+
|
|
99
|
+
# Cluster-wide checks (run once)
|
|
100
|
+
self._check_cluster_rbac()
|
|
101
|
+
|
|
102
|
+
# Namespace-scoped checks
|
|
103
|
+
for ns in target_ns:
|
|
104
|
+
self._check_rbac(ns)
|
|
105
|
+
self._check_pod_security(ns)
|
|
106
|
+
self._check_network_policies(ns)
|
|
107
|
+
self._check_secrets(ns)
|
|
108
|
+
|
|
109
|
+
return self.findings
|
|
110
|
+
|
|
111
|
+
def _check_cluster_rbac(self):
|
|
112
|
+
"""Check cluster-wide RBAC configurations."""
|
|
113
|
+
# Check ClusterRoleBindings for cluster-admin
|
|
114
|
+
bindings = self._run_kubectl(["get", "clusterrolebindings"])
|
|
115
|
+
for binding in bindings.get("items", []):
|
|
116
|
+
role_name = binding.get("roleRef", {}).get("name", "")
|
|
117
|
+
binding_name = binding["metadata"]["name"]
|
|
118
|
+
|
|
119
|
+
# Skip system bindings
|
|
120
|
+
if binding_name.startswith("system:"):
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
if role_name == "cluster-admin":
|
|
124
|
+
for subject in binding.get("subjects", []):
|
|
125
|
+
if subject.get("kind") == "ServiceAccount":
|
|
126
|
+
self.findings.append(SecurityFinding(
|
|
127
|
+
check_id="RBAC-002",
|
|
128
|
+
title="ServiceAccount with cluster-admin",
|
|
129
|
+
description=f"ServiceAccount '{subject.get('name')}' in namespace '{subject.get('namespace', 'default')}' has cluster-admin binding via '{binding_name}'.",
|
|
130
|
+
severity=Severity.CRITICAL,
|
|
131
|
+
resource_kind="ClusterRoleBinding",
|
|
132
|
+
resource_name=binding_name,
|
|
133
|
+
namespace=subject.get("namespace", "cluster-wide"),
|
|
134
|
+
remediation="Remove cluster-admin binding. Create a scoped Role with minimum required permissions."
|
|
135
|
+
))
|
|
136
|
+
elif subject.get("kind") == "User" and not subject.get("name", "").startswith("system:"):
|
|
137
|
+
self.findings.append(SecurityFinding(
|
|
138
|
+
check_id="RBAC-003",
|
|
139
|
+
title="User with cluster-admin",
|
|
140
|
+
description=f"User '{subject.get('name')}' has cluster-admin binding via '{binding_name}'.",
|
|
141
|
+
severity=Severity.HIGH,
|
|
142
|
+
resource_kind="ClusterRoleBinding",
|
|
143
|
+
resource_name=binding_name,
|
|
144
|
+
namespace="cluster-wide",
|
|
145
|
+
remediation="Review if user truly needs cluster-admin. Apply least privilege principle."
|
|
146
|
+
))
|
|
147
|
+
|
|
148
|
+
def _get_all_namespaces(self) -> List[str]:
|
|
149
|
+
"""Get list of all namespaces."""
|
|
150
|
+
data = self._run_kubectl(["get", "namespaces"])
|
|
151
|
+
return [item["metadata"]["name"] for item in data.get("items", [])]
|
|
152
|
+
|
|
153
|
+
def _check_rbac(self, namespace: str):
|
|
154
|
+
"""Check for risky RBAC configurations."""
|
|
155
|
+
# Check 1: Roles with '*' verb
|
|
156
|
+
roles = self._run_kubectl(["get", "roles", "-n", namespace])
|
|
157
|
+
for role in roles.get("items", []):
|
|
158
|
+
name = role["metadata"]["name"]
|
|
159
|
+
for rule in role.get("rules", []):
|
|
160
|
+
if "*" in rule.get("verbs", []) and "*" in rule.get("resources", []):
|
|
161
|
+
self.findings.append(SecurityFinding(
|
|
162
|
+
check_id="RBAC-001",
|
|
163
|
+
title="Cluster Admin-like Role",
|
|
164
|
+
description=f"Role '{name}' has wildcard permissions (*/*).",
|
|
165
|
+
severity=Severity.CRITICAL,
|
|
166
|
+
resource_kind="Role",
|
|
167
|
+
resource_name=name,
|
|
168
|
+
namespace=namespace,
|
|
169
|
+
remediation="Apply least privilege. Remove wildcard permissions."
|
|
170
|
+
))
|
|
171
|
+
|
|
172
|
+
# Check 2: ServiceAccounts with cluster-admin binding
|
|
173
|
+
# (Simplified check - full graph analysis requires more logic)
|
|
174
|
+
|
|
175
|
+
def _check_pod_security(self, namespace: str):
|
|
176
|
+
"""Check pods against Pod Security Standards (PSS)."""
|
|
177
|
+
pods = self._run_kubectl(["get", "pods", "-n", namespace])
|
|
178
|
+
for pod in pods.get("items", []):
|
|
179
|
+
name = pod["metadata"]["name"]
|
|
180
|
+
spec = pod.get("spec", {})
|
|
181
|
+
|
|
182
|
+
# Check 1: Privileged containers
|
|
183
|
+
for container in spec.get("containers", []):
|
|
184
|
+
security_context = container.get("securityContext", {})
|
|
185
|
+
if security_context.get("privileged", False):
|
|
186
|
+
self.findings.append(SecurityFinding(
|
|
187
|
+
check_id="PSS-001",
|
|
188
|
+
title="Privileged Container",
|
|
189
|
+
description=f"Container '{container['name']}' in pod '{name}' runs as privileged.",
|
|
190
|
+
severity=Severity.HIGH,
|
|
191
|
+
resource_kind="Pod",
|
|
192
|
+
resource_name=name,
|
|
193
|
+
namespace=namespace,
|
|
194
|
+
remediation="Remove 'privileged: true' from securityContext unless absolutely necessary."
|
|
195
|
+
))
|
|
196
|
+
|
|
197
|
+
# Check 2: Host PID/Network/IPC
|
|
198
|
+
if spec.get("hostPID") or spec.get("hostNetwork") or spec.get("hostIPC"):
|
|
199
|
+
self.findings.append(SecurityFinding(
|
|
200
|
+
check_id="PSS-002",
|
|
201
|
+
title="Host Namespace Usage",
|
|
202
|
+
description=f"Pod '{name}' shares host namespaces (PID/Net/IPC).",
|
|
203
|
+
severity=Severity.HIGH,
|
|
204
|
+
resource_kind="Pod",
|
|
205
|
+
resource_name=name,
|
|
206
|
+
namespace=namespace,
|
|
207
|
+
remediation="Disable hostPID, hostNetwork, and hostIPC."
|
|
208
|
+
))
|
|
209
|
+
|
|
210
|
+
def _check_network_policies(self, namespace: str):
|
|
211
|
+
"""Check if network policies are defined."""
|
|
212
|
+
policies = self._run_kubectl(["get", "networkpolicies", "-n", namespace])
|
|
213
|
+
if not policies.get("items"):
|
|
214
|
+
self.findings.append(SecurityFinding(
|
|
215
|
+
check_id="NET-001",
|
|
216
|
+
title="Missing Network Policy",
|
|
217
|
+
description=f"Namespace '{namespace}' has no NetworkPolicies defined. Traffic is unrestricted.",
|
|
218
|
+
severity=Severity.MEDIUM,
|
|
219
|
+
resource_kind="Namespace",
|
|
220
|
+
resource_name=namespace,
|
|
221
|
+
namespace=namespace,
|
|
222
|
+
remediation="Define a default deny-all NetworkPolicy."
|
|
223
|
+
))
|
|
224
|
+
|
|
225
|
+
def _check_secrets(self, namespace: str):
|
|
226
|
+
"""Check for secrets issues."""
|
|
227
|
+
pods = self._run_kubectl(["get", "pods", "-n", namespace])
|
|
228
|
+
for pod in pods.get("items", []):
|
|
229
|
+
name = pod["metadata"]["name"]
|
|
230
|
+
spec = pod.get("spec", {})
|
|
231
|
+
|
|
232
|
+
for container in spec.get("containers", []):
|
|
233
|
+
container_name = container.get("name", "unknown")
|
|
234
|
+
|
|
235
|
+
# Check for secrets in plain env vars (bad practice)
|
|
236
|
+
for env in container.get("env", []):
|
|
237
|
+
env_name = env.get("name", "").lower()
|
|
238
|
+
env_value = env.get("value", "")
|
|
239
|
+
|
|
240
|
+
# Skip if using secretKeyRef (proper method)
|
|
241
|
+
if env.get("valueFrom", {}).get("secretKeyRef"):
|
|
242
|
+
continue
|
|
243
|
+
|
|
244
|
+
# Check for suspicious env var names with plain values
|
|
245
|
+
sensitive_keywords = ["password", "secret", "key", "token",
|
|
246
|
+
"api_key", "apikey", "auth", "credential",
|
|
247
|
+
"private", "access_key", "secret_key"]
|
|
248
|
+
|
|
249
|
+
if any(kw in env_name for kw in sensitive_keywords) and env_value:
|
|
250
|
+
self.findings.append(SecurityFinding(
|
|
251
|
+
check_id="SEC-001",
|
|
252
|
+
title="Secret in Plain Environment Variable",
|
|
253
|
+
description=f"Container '{container_name}' in pod '{name}' has sensitive data in plain env var '{env.get('name')}'.",
|
|
254
|
+
severity=Severity.HIGH,
|
|
255
|
+
resource_kind="Pod",
|
|
256
|
+
resource_name=name,
|
|
257
|
+
namespace=namespace,
|
|
258
|
+
remediation="Use Kubernetes Secrets with secretKeyRef instead of plain values. Never commit secrets in manifests."
|
|
259
|
+
))
|
|
260
|
+
|
|
261
|
+
# Check for automountServiceAccountToken
|
|
262
|
+
if spec.get("automountServiceAccountToken", True):
|
|
263
|
+
# Only flag if not system namespace
|
|
264
|
+
if namespace not in ["kube-system", "kube-public", "kube-node-lease"]:
|
|
265
|
+
self.findings.append(SecurityFinding(
|
|
266
|
+
check_id="SEC-002",
|
|
267
|
+
title="ServiceAccount Token Auto-Mounted",
|
|
268
|
+
description=f"Pod '{name}' has automountServiceAccountToken enabled (default).",
|
|
269
|
+
severity=Severity.LOW,
|
|
270
|
+
resource_kind="Pod",
|
|
271
|
+
resource_name=name,
|
|
272
|
+
namespace=namespace,
|
|
273
|
+
remediation="Set automountServiceAccountToken: false unless the pod needs K8s API access."
|
|
274
|
+
))
|
|
275
|
+
|
|
276
|
+
def export_report(self) -> Dict[str, Any]:
|
|
277
|
+
"""Export findings summary."""
|
|
278
|
+
return {
|
|
279
|
+
"total_findings": len(self.findings),
|
|
280
|
+
"findings": [
|
|
281
|
+
{
|
|
282
|
+
"id": f.check_id,
|
|
283
|
+
"title": f.title,
|
|
284
|
+
"severity": f.severity.value,
|
|
285
|
+
"resource": f"{f.namespace}/{f.resource_kind}/{f.resource_name}",
|
|
286
|
+
"remediation": f.remediation
|
|
287
|
+
}
|
|
288
|
+
for f in self.findings
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
# === Convenience Functions ===
|
|
294
|
+
|
|
295
|
+
def scan_cluster(context: Optional[str] = None) -> Dict[str, Any]:
|
|
296
|
+
"""Run a full cluster scan."""
|
|
297
|
+
scanner = K8sScanner(context=context)
|
|
298
|
+
scanner.scan()
|
|
299
|
+
return scanner.export_report()
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def check_rbac(namespace: str = "default") -> List[Dict[str, Any]]:
|
|
303
|
+
"""Run RBAC checks only."""
|
|
304
|
+
scanner = K8sScanner()
|
|
305
|
+
scanner._check_rbac(namespace)
|
|
306
|
+
return scanner.export_report()["findings"]
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def check_pod_security(namespace: str = "default") -> List[Dict[str, Any]]:
|
|
310
|
+
"""Run Pod Security checks only."""
|
|
311
|
+
scanner = K8sScanner()
|
|
312
|
+
scanner._check_pod_security(namespace)
|
|
313
|
+
return scanner.export_report()["findings"]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AI Prompt Injection Scanner - Detect LLM vulnerabilities in AI applications.
|
|
3
|
+
|
|
4
|
+
This module provides tools for testing AI/LLM applications for:
|
|
5
|
+
- Direct prompt injection
|
|
6
|
+
- Indirect prompt injection
|
|
7
|
+
- Jailbreak attempts
|
|
8
|
+
- Data exfiltration via prompts
|
|
9
|
+
- System prompt leakage
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from .prompt_injection_actions import (
|
|
13
|
+
PromptInjectionScanner,
|
|
14
|
+
scan_for_prompt_injection,
|
|
15
|
+
generate_injection_payloads,
|
|
16
|
+
analyze_llm_response,
|
|
17
|
+
detect_jailbreak_success,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"PromptInjectionScanner",
|
|
22
|
+
"scan_for_prompt_injection",
|
|
23
|
+
"generate_injection_payloads",
|
|
24
|
+
"analyze_llm_response",
|
|
25
|
+
"detect_jailbreak_success",
|
|
26
|
+
]
|