eva-exploit 3.4.2__tar.gz → 3.4.3__tar.gz
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.
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/PKG-INFO +1 -1
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/config.py +1 -1
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/eva_exploit.egg-info/PKG-INFO +1 -1
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/modules/llm.py +68 -17
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/pyproject.toml +1 -1
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/sessions/eva_session.py +3 -2
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/utils/system.py +116 -36
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/README.md +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/eva.py +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/eva_exploit.egg-info/SOURCES.txt +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/eva_exploit.egg-info/dependency_links.txt +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/eva_exploit.egg-info/entry_points.txt +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/eva_exploit.egg-info/requires.txt +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/eva_exploit.egg-info/top_level.txt +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/modules/__init__.py +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/modules/attack_map.py +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/modules/exploit_search.py +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/modules/prompt_builder.py +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/modules/reporting.py +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/modules/tooling.py +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/modules/vuln_intel.py +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/modules/workflow.py +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/sessions/__init__.py +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/setup.cfg +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/utils/__init__.py +0 -0
- {eva_exploit-3.4.2 → eva_exploit-3.4.3}/utils/ui.py +0 -0
|
@@ -703,10 +703,59 @@ def _query_g4f(history):
|
|
|
703
703
|
return ""
|
|
704
704
|
|
|
705
705
|
|
|
706
|
-
def
|
|
706
|
+
def normalize_util(session_name):
|
|
707
|
+
suffix = re.sub(r"[^A-Za-z0-9_]", "_", str(session_name or "").strip())
|
|
708
|
+
suffix = re.sub(r"_+", "_", suffix).strip("_")
|
|
709
|
+
return suffix
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
def custom_enpdoint_func(session_name=""):
|
|
707
713
|
endpoint = str(getattr(config_module, "API_ENDPOINT", API_ENDPOINT) or "").strip()
|
|
708
714
|
if endpoint == "NOT_SET":
|
|
709
715
|
endpoint = ""
|
|
716
|
+
|
|
717
|
+
session_name = str(session_name or "").strip()
|
|
718
|
+
if session_name:
|
|
719
|
+
session_key = f"EVA_API_CUSTOMAPI_{session_name}"
|
|
720
|
+
session_endpoint = os.getenv(session_key, "").strip()
|
|
721
|
+
if session_endpoint:
|
|
722
|
+
return session_endpoint
|
|
723
|
+
|
|
724
|
+
normalized_suffix = normalize_util(session_name)
|
|
725
|
+
if normalized_suffix and normalized_suffix != session_name:
|
|
726
|
+
normalized_key = f"EVA_API_CUSTOMAPI_{normalized_suffix}"
|
|
727
|
+
normalized_endpoint = os.getenv(normalized_key, "").strip()
|
|
728
|
+
if normalized_endpoint:
|
|
729
|
+
return normalized_endpoint
|
|
730
|
+
|
|
731
|
+
return endpoint
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
def _call_custom_api_handler(query_fn, history, endpoint, prompt_text, session_name):
|
|
735
|
+
attempts = [
|
|
736
|
+
lambda: query_fn(history=history, endpoint=endpoint, prompt=prompt_text, session=session_name),
|
|
737
|
+
lambda: query_fn(history=history, endpoint=endpoint, session=session_name, prompt=prompt_text),
|
|
738
|
+
lambda: query_fn(history=history, endpoint=endpoint, prompt=prompt_text),
|
|
739
|
+
lambda: query_fn(history=history, endpoint=endpoint),
|
|
740
|
+
lambda: query_fn(history, endpoint, prompt_text, session_name),
|
|
741
|
+
lambda: query_fn(history, endpoint, prompt_text),
|
|
742
|
+
lambda: query_fn(history, endpoint),
|
|
743
|
+
lambda: query_fn(history),
|
|
744
|
+
]
|
|
745
|
+
last_type_error = None
|
|
746
|
+
for call in attempts:
|
|
747
|
+
try:
|
|
748
|
+
return call()
|
|
749
|
+
except TypeError as e:
|
|
750
|
+
last_type_error = e
|
|
751
|
+
|
|
752
|
+
if last_type_error is not None:
|
|
753
|
+
raise last_type_error
|
|
754
|
+
return ""
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
def _query_custom_api(history, prompt_text="", session_name=""):
|
|
758
|
+
endpoint = custom_enpdoint_func(session_name=session_name)
|
|
710
759
|
handler_path = str(getattr(config_module, "CUSTOM_API_HANDLER", CUSTOM_API_HANDLER) or "").strip()
|
|
711
760
|
|
|
712
761
|
if handler_path and handler_path != "NOT_SET":
|
|
@@ -720,19 +769,13 @@ def _query_custom_api(history, prompt_text=""):
|
|
|
720
769
|
spec.loader.exec_module(module)
|
|
721
770
|
query_fn = getattr(module, "query_custom_api", None)
|
|
722
771
|
if callable(query_fn):
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
result = query_fn(history, endpoint, prompt_text)
|
|
731
|
-
except TypeError:
|
|
732
|
-
try:
|
|
733
|
-
result = query_fn(history, endpoint)
|
|
734
|
-
except TypeError:
|
|
735
|
-
result = query_fn(history)
|
|
772
|
+
result = _call_custom_api_handler(
|
|
773
|
+
query_fn,
|
|
774
|
+
history=history,
|
|
775
|
+
endpoint=endpoint,
|
|
776
|
+
prompt_text=prompt_text,
|
|
777
|
+
session_name=session_name,
|
|
778
|
+
)
|
|
736
779
|
if isinstance(result, (dict, list)):
|
|
737
780
|
return json.dumps(result)
|
|
738
781
|
if result is None:
|
|
@@ -745,7 +788,7 @@ def _query_custom_api(history, prompt_text=""):
|
|
|
745
788
|
print(Fore.RED + "⚠️ Custom API endpoint is not configured.")
|
|
746
789
|
return ""
|
|
747
790
|
|
|
748
|
-
payload = {"conversation": history, "prompt": prompt_text}
|
|
791
|
+
payload = {"conversation": history, "prompt": prompt_text, "session": session_name}
|
|
749
792
|
r = requests.post(endpoint, json=payload, timeout=None)
|
|
750
793
|
return r.text
|
|
751
794
|
|
|
@@ -855,10 +898,14 @@ def _query_gemini(history):
|
|
|
855
898
|
|
|
856
899
|
|
|
857
900
|
class LLM:
|
|
858
|
-
def __init__(self, backend):
|
|
901
|
+
def __init__(self, backend, session_name=""):
|
|
859
902
|
self.backend = backend
|
|
903
|
+
self.session_name = str(session_name or "").strip()
|
|
860
904
|
self.history = []
|
|
861
905
|
|
|
906
|
+
def set_session_name(self, session_name):
|
|
907
|
+
self.session_name = str(session_name or "").strip()
|
|
908
|
+
|
|
862
909
|
def query(self, user_msg, last_output="", on_stream_start=None, workflow_context=""):
|
|
863
910
|
followup = _is_followup_analysis_request(user_msg)
|
|
864
911
|
if followup and (
|
|
@@ -917,7 +964,11 @@ class LLM:
|
|
|
917
964
|
elif self.backend == "g4f":
|
|
918
965
|
raw = _query_g4f(request_messages)
|
|
919
966
|
elif self.backend == "api":
|
|
920
|
-
raw = _query_custom_api(
|
|
967
|
+
raw = _query_custom_api(
|
|
968
|
+
request_messages,
|
|
969
|
+
prompt_text=prompt,
|
|
970
|
+
session_name=self.session_name,
|
|
971
|
+
)
|
|
921
972
|
elif self.backend == "gpt":
|
|
922
973
|
raw = _query_openai(request_messages)
|
|
923
974
|
elif self.backend == "anthropic":
|
|
@@ -95,7 +95,7 @@ class Eva:
|
|
|
95
95
|
self.memory = json.loads(session_path.read_text())
|
|
96
96
|
self.backend = self.memory.get("backend", backend)
|
|
97
97
|
|
|
98
|
-
self.model = LLM(self.backend)
|
|
98
|
+
self.model = LLM(self.backend, self.sessionName)
|
|
99
99
|
self._hydrate_model_context()
|
|
100
100
|
|
|
101
101
|
def _hydrate_model_context(self):
|
|
@@ -164,7 +164,7 @@ class Eva:
|
|
|
164
164
|
checkAPI()
|
|
165
165
|
self.memory["backend"] = self.backend
|
|
166
166
|
self.save()
|
|
167
|
-
self.model = LLM(self.backend)
|
|
167
|
+
self.model = LLM(self.backend, self.sessionName)
|
|
168
168
|
self._hydrate_model_context()
|
|
169
169
|
|
|
170
170
|
def rename_session(self):
|
|
@@ -189,6 +189,7 @@ class Eva:
|
|
|
189
189
|
self.session_path.rename(new_path)
|
|
190
190
|
self.session_path = new_path
|
|
191
191
|
self.sessionName = new_name
|
|
192
|
+
self.model.set_session_name(self.sessionName)
|
|
192
193
|
self.save()
|
|
193
194
|
cyber(f"Session renamed to {new_name}", color=Fore.GREEN)
|
|
194
195
|
|
|
@@ -70,7 +70,7 @@ def _custom_api_template(endpoint):
|
|
|
70
70
|
"#!/usr/bin/env python3\n"
|
|
71
71
|
"import requests\n\n"
|
|
72
72
|
f"API_ENDPOINT = {json.dumps(target)}\n\n"
|
|
73
|
-
"def query_custom_api(history, endpoint=None, prompt=None):\n"
|
|
73
|
+
"def query_custom_api(history, endpoint=None, session=None, prompt=None):\n"
|
|
74
74
|
" target = endpoint or API_ENDPOINT\n"
|
|
75
75
|
" compiled_prompt = str(prompt or \"\").strip()\n"
|
|
76
76
|
" if not compiled_prompt:\n"
|
|
@@ -81,7 +81,7 @@ def _custom_api_template(endpoint):
|
|
|
81
81
|
" payload = {\n"
|
|
82
82
|
" \"prompt\": compiled_prompt,\n"
|
|
83
83
|
" \"conversation\": history,\n"
|
|
84
|
-
" \"session\":
|
|
84
|
+
" \"session\": session,\n"
|
|
85
85
|
" }\n"
|
|
86
86
|
" r = requests.post(target, json=payload, timeout=None)\n"
|
|
87
87
|
" try:\n"
|
|
@@ -249,11 +249,74 @@ def _is_newer(latest, current):
|
|
|
249
249
|
_UPDATE_STATUS_CACHE = None
|
|
250
250
|
|
|
251
251
|
|
|
252
|
+
def _module_git_root():
|
|
253
|
+
here = Path(__file__).resolve()
|
|
254
|
+
for base in (here.parent, *here.parents):
|
|
255
|
+
if (base / ".git").exists():
|
|
256
|
+
return base
|
|
257
|
+
return None
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _installed_package_version():
|
|
261
|
+
try:
|
|
262
|
+
return metadata.version(PYPI_PACKAGE)
|
|
263
|
+
except metadata.PackageNotFoundError:
|
|
264
|
+
return None
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _is_path_in_repo(raw_path, repo_root):
|
|
268
|
+
if not raw_path:
|
|
269
|
+
return False
|
|
270
|
+
try:
|
|
271
|
+
candidate = Path(raw_path).expanduser()
|
|
272
|
+
if not candidate.exists():
|
|
273
|
+
return False
|
|
274
|
+
candidate = candidate.resolve()
|
|
275
|
+
return candidate.is_relative_to(repo_root.resolve())
|
|
276
|
+
except OSError:
|
|
277
|
+
return False
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def _running_from_repo_checkout(repo_root):
|
|
281
|
+
main_module = sys.modules.get("__main__")
|
|
282
|
+
main_file = getattr(main_module, "__file__", "")
|
|
283
|
+
if _is_path_in_repo(main_file, repo_root):
|
|
284
|
+
return True
|
|
285
|
+
argv0 = sys.argv[0] if sys.argv else ""
|
|
286
|
+
if argv0 and Path(argv0).expanduser().exists() and _is_path_in_repo(argv0, repo_root):
|
|
287
|
+
return True
|
|
288
|
+
return False
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def _read_local_version(base_path):
|
|
292
|
+
pyproject = base_path / "pyproject.toml"
|
|
293
|
+
if pyproject.exists():
|
|
294
|
+
try:
|
|
295
|
+
data = tomllib.loads(pyproject.read_text(encoding="utf-8"))
|
|
296
|
+
version = data.get("project", {}).get("version")
|
|
297
|
+
if version:
|
|
298
|
+
return str(version).strip()
|
|
299
|
+
except (tomllib.TOMLDecodeError, OSError):
|
|
300
|
+
pass
|
|
301
|
+
|
|
302
|
+
cfg_path = base_path / "config.py"
|
|
303
|
+
if cfg_path.exists():
|
|
304
|
+
try:
|
|
305
|
+
raw = cfg_path.read_text(encoding="utf-8")
|
|
306
|
+
except OSError:
|
|
307
|
+
return None
|
|
308
|
+
match = re.search(r'^APP_VERSION\s*=\s*["\']([^"\']+)["\']', raw, flags=re.MULTILINE)
|
|
309
|
+
if match:
|
|
310
|
+
return match.group(1).strip()
|
|
311
|
+
return None
|
|
312
|
+
|
|
313
|
+
|
|
252
314
|
def _git_branch():
|
|
253
|
-
|
|
315
|
+
repo_root = _module_git_root()
|
|
316
|
+
if repo_root is None:
|
|
254
317
|
return "main"
|
|
255
318
|
branch_detect = subprocess.run(
|
|
256
|
-
["git", "rev-parse", "--abbrev-ref", "HEAD"],
|
|
319
|
+
["git", "-C", str(repo_root), "rev-parse", "--abbrev-ref", "HEAD"],
|
|
257
320
|
capture_output=True,
|
|
258
321
|
text=True
|
|
259
322
|
)
|
|
@@ -263,13 +326,15 @@ def _git_branch():
|
|
|
263
326
|
|
|
264
327
|
|
|
265
328
|
def _update_source():
|
|
266
|
-
|
|
329
|
+
repo_root = _module_git_root()
|
|
330
|
+
installed_version = _installed_package_version()
|
|
331
|
+
if repo_root is not None and command_exists("git") and _running_from_repo_checkout(repo_root):
|
|
267
332
|
return "github"
|
|
268
|
-
|
|
269
|
-
metadata.version(PYPI_PACKAGE)
|
|
333
|
+
if installed_version:
|
|
270
334
|
return "pypi"
|
|
271
|
-
|
|
335
|
+
if repo_root is not None and command_exists("git"):
|
|
272
336
|
return "github"
|
|
337
|
+
return "pypi"
|
|
273
338
|
|
|
274
339
|
|
|
275
340
|
def _can_reach_tls_host(host):
|
|
@@ -282,18 +347,25 @@ def _can_reach_tls_host(host):
|
|
|
282
347
|
|
|
283
348
|
|
|
284
349
|
def get_current_version():
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
350
|
+
repo_root = _module_git_root()
|
|
351
|
+
installed_version = _installed_package_version()
|
|
352
|
+
|
|
353
|
+
if repo_root is not None and _running_from_repo_checkout(repo_root):
|
|
354
|
+
local_version = _read_local_version(repo_root)
|
|
355
|
+
if local_version:
|
|
356
|
+
return local_version
|
|
357
|
+
|
|
358
|
+
if installed_version:
|
|
359
|
+
return installed_version
|
|
360
|
+
|
|
361
|
+
if repo_root is not None:
|
|
362
|
+
local_version = _read_local_version(repo_root)
|
|
363
|
+
if local_version:
|
|
364
|
+
return local_version
|
|
365
|
+
|
|
366
|
+
local_version = _read_local_version(Path.cwd())
|
|
367
|
+
if local_version:
|
|
368
|
+
return local_version
|
|
297
369
|
return APP_VERSION
|
|
298
370
|
|
|
299
371
|
|
|
@@ -339,7 +411,11 @@ def get_update_status(force=False):
|
|
|
339
411
|
latest = None
|
|
340
412
|
available = bool(latest) and _is_newer(latest, current)
|
|
341
413
|
|
|
342
|
-
|
|
414
|
+
repo_root = _module_git_root()
|
|
415
|
+
if source == "github" and repo_root is not None:
|
|
416
|
+
command = f"git -C {shlex.quote(str(repo_root))} pull --tags origin {branch}"
|
|
417
|
+
else:
|
|
418
|
+
command = "eva -u"
|
|
343
419
|
prefix = "|> Update github checkout running " if source == "github" else "|> Update eva to latest version running "
|
|
344
420
|
|
|
345
421
|
_UPDATE_STATUS_CACHE = {
|
|
@@ -377,21 +453,22 @@ def run_self_update():
|
|
|
377
453
|
source = status.get("source")
|
|
378
454
|
print(Style.BRIGHT + Fore.MAGENTA + f"Update {latest} found! Installing . . . . " + Style.RESET_ALL)
|
|
379
455
|
|
|
456
|
+
repo_root = _module_git_root()
|
|
380
457
|
updated = False
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
458
|
+
if source == "github" and repo_root is not None and command_exists("git"):
|
|
459
|
+
branch = _git_branch()
|
|
460
|
+
pull_result = subprocess.run(
|
|
461
|
+
["git", "-C", str(repo_root), "pull", "--tags", "origin", branch],
|
|
462
|
+
text=True
|
|
463
|
+
)
|
|
464
|
+
updated = pull_result.returncode == 0
|
|
465
|
+
else:
|
|
466
|
+
pip_cmd = [sys.executable, "-m", "pip", "install", "--upgrade", PYPI_PACKAGE, "--break-system-packages"]
|
|
467
|
+
pip_result = subprocess.run(pip_cmd, text=True, capture_output=True)
|
|
468
|
+
if pip_result.returncode != 0 and "no such option: --break-system-packages" in (pip_result.stderr or "").lower():
|
|
469
|
+
pip_cmd = [sys.executable, "-m", "pip", "install", "--upgrade", PYPI_PACKAGE]
|
|
470
|
+
pip_result = subprocess.run(pip_cmd, text=True)
|
|
471
|
+
updated = pip_result.returncode == 0
|
|
395
472
|
|
|
396
473
|
print(Fore.CYAN + "Almost done . . . . ")
|
|
397
474
|
if updated:
|
|
@@ -402,7 +479,10 @@ def run_self_update():
|
|
|
402
479
|
|
|
403
480
|
print(Fore.RED + "\n[!] Could not auto-update EVA in this environment.")
|
|
404
481
|
if source == "github":
|
|
405
|
-
|
|
482
|
+
if repo_root is not None:
|
|
483
|
+
print(Fore.YELLOW + f"Try manually: git -C {shlex.quote(str(repo_root))} pull --tags origin {_git_branch()}")
|
|
484
|
+
else:
|
|
485
|
+
print(Fore.YELLOW + f"Try manually: git pull --tags origin {_git_branch()}")
|
|
406
486
|
else:
|
|
407
487
|
print(Fore.YELLOW + f"Try manually: {sys.executable} -m pip install --upgrade {PYPI_PACKAGE}")
|
|
408
488
|
return 1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|