voidaccess 1.4.0__tar.gz → 1.4.2__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.
- {voidaccess-1.4.0 → voidaccess-1.4.2}/PKG-INFO +1 -1
- {voidaccess-1.4.0 → voidaccess-1.4.2}/pyproject.toml +1 -1
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess.egg-info/PKG-INFO +1 -1
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/__init__.py +1 -1
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/commands/export.py +7 -3
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/commands/investigate.py +20 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/commands/show.py +22 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/config.py +6 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/main.py +22 -10
- {voidaccess-1.4.0 → voidaccess-1.4.2}/LICENSE +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/README.md +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/analysis/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/analysis/opsec.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/analysis/patterns.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/analysis/temporal.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/auth.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/main.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/routes/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/routes/admin.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/routes/auth.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/routes/entities.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/routes/export.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/routes/investigations.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/routes/monitors.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/routes/search.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/api/routes/settings.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/auth/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/auth/token_blacklist.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/config.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/crawler/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/crawler/dedup.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/crawler/frontier.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/crawler/spider.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/crawler/utils.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/env.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0001_initial_schema.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0002_add_investigation_status_column.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0002_add_missing_tables.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0003_add_canonical_value_and_entity_links.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0004_add_page_posted_at.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0005_add_extraction_method.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0006_add_monitor_alerts.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0007_add_actor_style_profiles.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0008_add_users_table.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0009_add_investigation_id_to_relationships.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0010_add_composite_index_entity_relationships.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0011_add_page_extraction_cache.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0013_add_graph_status.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0015_add_progress_fields.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0016_backfill_graph_status.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0017_add_user_api_keys.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0018_add_user_id_to_investigations.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0019_add_content_safety_log.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0020_add_entity_source_tracking.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/models.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/queries.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/db/session.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/export/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/export/misp.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/export/sigma.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/export/stix.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/extractor/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/extractor/llm_extract.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/extractor/ner.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/extractor/normalizer.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/extractor/pipeline.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/extractor/regex_patterns.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/fingerprint/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/fingerprint/profiler.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/fingerprint/stylometry.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/graph/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/graph/builder.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/graph/export.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/graph/model.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/graph/queries.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/graph/visualize.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/i18n/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/i18n/detect.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/i18n/query_expand.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/i18n/translate.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/monitor/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/monitor/_db.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/monitor/alerts.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/monitor/config.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/monitor/diff.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/monitor/jobs.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/monitor/scheduler.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/scraper/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/scraper/scrape.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/scraper/scrape_js.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/search/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/search/circuit_breaker.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/search/search.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/setup.cfg +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/blockchain.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/cache.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/cisa.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/dns_enrichment.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/domain_reputation.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/email_reputation.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/engines.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/enrichment.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/github_scraper.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/gitlab_scraper.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/hash_reputation.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/historical_intel.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/ip_reputation.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/paste_scraper.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/pastes.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/rss_scraper.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/seed_manager.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/seeds.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/shodan.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/telegram.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/sources/virustotal.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_analysis_opsec.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_analysis_stylometry.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_analysis_temporal.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_api.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_api_monitors.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_blockchain.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_config.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_crawler.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_db.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_dns_enrichment.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_domain_reputation.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_email_reputation.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_fingerprint.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_github_scraper.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_gitlab_scraper.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_graph.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_hash_reputation.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_i18n.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_ip_reputation.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_llm.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_llm_utils.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_model_singleton.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_monitor.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_pagination.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_paste_scraper.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_rss_scraper.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_scrape_js.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_settings.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_sources.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_sources_enrichment_new.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/tests/test_vector.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/utils/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/utils/async_utils.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/utils/content_safety.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/utils/defang.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/utils/encryption.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/utils/ioc_freshness.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/utils/user_keys.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/vector/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/vector/embedder.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/vector/model_singleton.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/vector/search.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/vector/store.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess/llm.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess/llm_utils.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess.egg-info/SOURCES.txt +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess.egg-info/dependency_links.txt +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess.egg-info/entry_points.txt +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess.egg-info/requires.txt +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess.egg-info/top_level.txt +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/adapters/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/adapters/sqlite.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/browser.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/commands/__init__.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/commands/configure.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/commands/enrich.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/display.py +0 -0
- {voidaccess-1.4.0 → voidaccess-1.4.2}/voidaccess_cli/tor_detect.py +0 -0
|
@@ -39,7 +39,7 @@ def run(
|
|
|
39
39
|
raise typer.Exit(code=1)
|
|
40
40
|
|
|
41
41
|
payload, suffix = _render(fmt, inv_id, data)
|
|
42
|
-
out_path = output or _default_out_path(target, suffix)
|
|
42
|
+
out_path = output or _default_out_path(target, suffix, fmt=fmt)
|
|
43
43
|
out_path = Path(out_path).expanduser()
|
|
44
44
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
45
45
|
if isinstance(payload, bytes):
|
|
@@ -150,9 +150,13 @@ def _flatten_for_md(data: dict) -> dict:
|
|
|
150
150
|
return data
|
|
151
151
|
|
|
152
152
|
|
|
153
|
-
def _default_out_path(target: str, suffix: str) -> Path:
|
|
153
|
+
def _default_out_path(target: str, suffix: str, fmt: str = "") -> Path:
|
|
154
154
|
p = Path(target).expanduser()
|
|
155
155
|
if p.exists():
|
|
156
|
-
|
|
156
|
+
candidate = p.with_suffix(suffix)
|
|
157
|
+
# Avoid overwriting input when suffix is the same (e.g. stix/misp .json)
|
|
158
|
+
if candidate == p and fmt and fmt not in ("json",):
|
|
159
|
+
return p.parent / f"{p.stem}-{fmt}{suffix}"
|
|
160
|
+
return candidate
|
|
157
161
|
from voidaccess_cli import config as cli_config
|
|
158
162
|
return cli_config.get_output_dir() / f"{target}{suffix}"
|
|
@@ -49,9 +49,28 @@ def run(
|
|
|
49
49
|
from voidaccess_cli import config as cli_config
|
|
50
50
|
|
|
51
51
|
cli_config.apply_env()
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
import spacy
|
|
55
|
+
spacy.load("en_core_web_sm")
|
|
56
|
+
except Exception:
|
|
57
|
+
import subprocess, sys
|
|
58
|
+
from rich.console import Console
|
|
59
|
+
Console().print(" [dim]→[/dim] Installing spaCy NER model (one-time)...")
|
|
60
|
+
subprocess.run(
|
|
61
|
+
[sys.executable, "-m", "spacy", "download", "en_core_web_sm"],
|
|
62
|
+
capture_output=True,
|
|
63
|
+
)
|
|
64
|
+
|
|
52
65
|
if quiet:
|
|
53
66
|
logging.getLogger().setLevel(logging.ERROR)
|
|
54
67
|
|
|
68
|
+
from utils.content_safety import is_blocked_query
|
|
69
|
+
blocked, reason = is_blocked_query(query)
|
|
70
|
+
if blocked:
|
|
71
|
+
console.print(f"[red]Query blocked:[/red] {reason}")
|
|
72
|
+
raise typer.Exit(code=1)
|
|
73
|
+
|
|
55
74
|
if not cli_config.is_configured() and not no_llm:
|
|
56
75
|
console.print("[yellow]No LLM configured.[/yellow] Run [bold]voidaccess configure[/bold] first, or pass --no-llm.")
|
|
57
76
|
raise typer.Exit(code=2)
|
|
@@ -382,6 +401,7 @@ async def _run_investigation(
|
|
|
382
401
|
"query": query,
|
|
383
402
|
"refined_query": refined,
|
|
384
403
|
"model_used": chosen_model if llm is not None else None,
|
|
404
|
+
"status": "completed" if final_entities or scraped_pages else "completed_no_results",
|
|
385
405
|
"created_at": datetime.now(timezone.utc).isoformat(),
|
|
386
406
|
"summary": summary_text,
|
|
387
407
|
"sources_used": sources_used,
|
|
@@ -24,6 +24,7 @@ def run(
|
|
|
24
24
|
target: Optional[str] = typer.Argument(
|
|
25
25
|
None, help="Investigation id or path to a .json export"
|
|
26
26
|
),
|
|
27
|
+
no_tui: bool = typer.Option(False, "--no-tui", help="Print summary table without launching TUI (for scripted use)."),
|
|
27
28
|
) -> None:
|
|
28
29
|
"""Open the entity browser TUI."""
|
|
29
30
|
from voidaccess_cli import config as cli_config
|
|
@@ -32,6 +33,9 @@ def run(
|
|
|
32
33
|
data: Optional[dict] = None
|
|
33
34
|
|
|
34
35
|
if target is None:
|
|
36
|
+
if no_tui:
|
|
37
|
+
console.print("[yellow]No target specified.[/yellow]")
|
|
38
|
+
raise typer.Exit(code=1)
|
|
35
39
|
target = _pick_recent()
|
|
36
40
|
if target is None:
|
|
37
41
|
console.print("[yellow]No investigations found. Run `voidaccess investigate` first.[/yellow]")
|
|
@@ -49,11 +53,29 @@ def run(
|
|
|
49
53
|
console.print(f"[red]Unknown investigation:[/red] {target}")
|
|
50
54
|
raise typer.Exit(code=1)
|
|
51
55
|
|
|
56
|
+
if no_tui:
|
|
57
|
+
_print_summary(data)
|
|
58
|
+
return
|
|
59
|
+
|
|
52
60
|
from voidaccess_cli.browser import EntityBrowserApp
|
|
53
61
|
app = EntityBrowserApp(data=data)
|
|
54
62
|
app.run()
|
|
55
63
|
|
|
56
64
|
|
|
65
|
+
def _print_summary(data: dict) -> None:
|
|
66
|
+
inv = data.get("investigation") or data
|
|
67
|
+
entities = data.get("entities", [])
|
|
68
|
+
table = Table(title="Investigation summary")
|
|
69
|
+
table.add_column("Field", style="bold")
|
|
70
|
+
table.add_column("Value")
|
|
71
|
+
table.add_row("Query", str(inv.get("query") or ""))
|
|
72
|
+
table.add_row("Status", str(inv.get("status") or ""))
|
|
73
|
+
table.add_row("Entities", str(len(entities)))
|
|
74
|
+
table.add_row("Created", str(inv.get("created_at") or "")[:19])
|
|
75
|
+
table.add_row("Summary", (str(inv.get("summary") or "—"))[:120])
|
|
76
|
+
console.print(table)
|
|
77
|
+
|
|
78
|
+
|
|
57
79
|
def _pick_recent() -> Optional[str]:
|
|
58
80
|
from voidaccess_cli.adapters import sqlite as sqlite_adapter
|
|
59
81
|
sqlite_adapter.init_db()
|
|
@@ -178,3 +178,9 @@ def apply_env(config: Optional[dict[str, Any]] = None) -> None:
|
|
|
178
178
|
# Enrichment keys
|
|
179
179
|
for k, v in (cfg.get("enrichment_keys") or {}).items():
|
|
180
180
|
_set_env_if_present(k, v, clear_if_empty=True)
|
|
181
|
+
|
|
182
|
+
# Keyless APIs (ThreatFox/URLhaus/MalwareBazaar/abuse.ch) must never
|
|
183
|
+
# receive an empty auth header — clear any empty env remnant.
|
|
184
|
+
for key in ("ABUSECH_API_KEY", "VT_API_KEY", "OTX_API_KEY"):
|
|
185
|
+
if not os.environ.get(key):
|
|
186
|
+
os.environ.pop(key, None)
|
|
@@ -14,6 +14,7 @@ import sys
|
|
|
14
14
|
# Force UTF-8 on Windows consoles so rich glyphs render reliably
|
|
15
15
|
if sys.platform == "win32":
|
|
16
16
|
os.environ.setdefault("PYTHONIOENCODING", "utf-8")
|
|
17
|
+
os.environ.setdefault("PYTHONUTF8", "1")
|
|
17
18
|
try:
|
|
18
19
|
sys.stdout.reconfigure(encoding="utf-8") # type: ignore[attr-defined]
|
|
19
20
|
sys.stderr.reconfigure(encoding="utf-8") # type: ignore[attr-defined]
|
|
@@ -21,6 +22,7 @@ if sys.platform == "win32":
|
|
|
21
22
|
pass
|
|
22
23
|
|
|
23
24
|
import typer
|
|
25
|
+
from rich.align import Align
|
|
24
26
|
from rich.console import Console
|
|
25
27
|
from rich.table import Table
|
|
26
28
|
|
|
@@ -30,13 +32,17 @@ from voidaccess_cli.commands import configure, enrich, export, investigate, show
|
|
|
30
32
|
|
|
31
33
|
console = Console()
|
|
32
34
|
BANNER = """\
|
|
33
|
-
[color(183)]
|
|
34
|
-
[color(183)]
|
|
35
|
-
[color(183)]
|
|
36
|
-
[color(183)]
|
|
37
|
-
[color(183)]
|
|
38
|
-
[color(
|
|
39
|
-
[color(183)]
|
|
35
|
+
[color(183)] ░░░░░[color(141)]█[color(183)]░░░░░[/]
|
|
36
|
+
[color(183)] ░░[color(141)]█████████████[color(183)]░░[/]
|
|
37
|
+
[color(183)] ░[color(141)]█████████████████[color(183)]░[/]
|
|
38
|
+
[color(183)]░[color(141)]███████████████████[color(183)]░[/]
|
|
39
|
+
[color(183)]░[color(141)]███████████████████[color(183)]░[/]
|
|
40
|
+
[color(141)]██████[/] [bright_white]void[/] [color(141)]███████[/]
|
|
41
|
+
[color(183)]░[color(141)]███████████████████[color(183)]░[/]
|
|
42
|
+
[color(183)]░[color(141)]███████████████████[color(183)]░[/]
|
|
43
|
+
[color(183)] ░[color(141)]█████████████████[color(183)]░[/]
|
|
44
|
+
[color(183)] ░░[color(141)]█████████████[color(183)]░░[/]
|
|
45
|
+
[color(183)] ░░░░░[color(141)]█[color(183)]░░░░░[/]
|
|
40
46
|
[dim white] dark web osint intelligence[/dim white]"""
|
|
41
47
|
|
|
42
48
|
app = typer.Typer(
|
|
@@ -154,10 +160,16 @@ def version() -> None:
|
|
|
154
160
|
|
|
155
161
|
|
|
156
162
|
def show_banner(console: Console) -> None:
|
|
157
|
-
|
|
163
|
+
import shutil
|
|
164
|
+
if os.environ.get("TERM") == "dumb":
|
|
165
|
+
return
|
|
166
|
+
if not sys.stdout.isatty() and "PS1" not in os.environ and os.name != "nt":
|
|
158
167
|
return
|
|
159
168
|
console.print()
|
|
160
|
-
|
|
169
|
+
raw_line = " oooooXooooo " # widest line, 21 chars
|
|
170
|
+
pad = max(0, (console.width - len(raw_line)) // 2)
|
|
171
|
+
for line in BANNER.split("\n"):
|
|
172
|
+
console.print(" " * pad + line)
|
|
161
173
|
console.print()
|
|
162
174
|
|
|
163
175
|
|
|
@@ -171,7 +183,7 @@ def main(
|
|
|
171
183
|
) -> None:
|
|
172
184
|
"""Set env vars and render banner before command execution."""
|
|
173
185
|
cli_config.apply_env()
|
|
174
|
-
if not no_banner and
|
|
186
|
+
if not no_banner and ctx.invoked_subcommand:
|
|
175
187
|
show_banner(console)
|
|
176
188
|
|
|
177
189
|
|
|
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
|
|
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
|
{voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0002_add_investigation_status_column.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0007_add_actor_style_profiles.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0011_add_page_extraction_cache.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0018_add_user_id_to_investigations.py
RENAMED
|
File without changes
|
|
File without changes
|
{voidaccess-1.4.0 → voidaccess-1.4.2}/db/migrations/versions/0020_add_entity_source_tracking.py
RENAMED
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|