cyberfw 2.0.0__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.
Files changed (156) hide show
  1. cyberfw-2.0.0/.gitignore +62 -0
  2. cyberfw-2.0.0/CHANGELOG.md +489 -0
  3. cyberfw-2.0.0/LICENSE +21 -0
  4. cyberfw-2.0.0/PKG-INFO +1163 -0
  5. cyberfw-2.0.0/README.md +1134 -0
  6. cyberfw-2.0.0/cyberfw/__init__.py +21 -0
  7. cyberfw-2.0.0/cyberfw/__main__.py +5 -0
  8. cyberfw-2.0.0/cyberfw/api.py +426 -0
  9. cyberfw-2.0.0/cyberfw/cli/__init__.py +28 -0
  10. cyberfw-2.0.0/cyberfw/cli/__main__.py +5 -0
  11. cyberfw-2.0.0/cyberfw/cli/app.py +13 -0
  12. cyberfw-2.0.0/cyberfw/cli/common.py +167 -0
  13. cyberfw-2.0.0/cyberfw/cli/launcher.py +500 -0
  14. cyberfw-2.0.0/cyberfw/cli/plugins.py +121 -0
  15. cyberfw-2.0.0/cyberfw/cli/reports.py +127 -0
  16. cyberfw-2.0.0/cyberfw/cli/scan.py +601 -0
  17. cyberfw-2.0.0/cyberfw/cli/schedule.py +151 -0
  18. cyberfw-2.0.0/cyberfw/cli/tools.py +409 -0
  19. cyberfw-2.0.0/cyberfw/cli/triage.py +110 -0
  20. cyberfw-2.0.0/cyberfw/cli/views.py +661 -0
  21. cyberfw-2.0.0/cyberfw/completion.py +126 -0
  22. cyberfw-2.0.0/cyberfw/config.py +199 -0
  23. cyberfw-2.0.0/cyberfw/core/__init__.py +7 -0
  24. cyberfw-2.0.0/cyberfw/core/events.py +126 -0
  25. cyberfw-2.0.0/cyberfw/core/finish.py +143 -0
  26. cyberfw-2.0.0/cyberfw/core/plugins.py +97 -0
  27. cyberfw-2.0.0/cyberfw/core/scan.py +274 -0
  28. cyberfw-2.0.0/cyberfw/core/sessions.py +84 -0
  29. cyberfw-2.0.0/cyberfw/core/steps.py +180 -0
  30. cyberfw-2.0.0/cyberfw/core/tool_run.py +110 -0
  31. cyberfw-2.0.0/cyberfw/core/workspace.py +106 -0
  32. cyberfw-2.0.0/cyberfw/exceptions.py +130 -0
  33. cyberfw-2.0.0/cyberfw/hud.py +532 -0
  34. cyberfw-2.0.0/cyberfw/live_view.py +529 -0
  35. cyberfw-2.0.0/cyberfw/logging.py +103 -0
  36. cyberfw-2.0.0/cyberfw/manager/__init__.py +375 -0
  37. cyberfw-2.0.0/cyberfw/manager/archive.py +86 -0
  38. cyberfw-2.0.0/cyberfw/manager/chromium.py +229 -0
  39. cyberfw-2.0.0/cyberfw/manager/discovery.py +91 -0
  40. cyberfw-2.0.0/cyberfw/manager/github_client.py +368 -0
  41. cyberfw-2.0.0/cyberfw/manager/installer.py +378 -0
  42. cyberfw-2.0.0/cyberfw/manager/lock.py +376 -0
  43. cyberfw-2.0.0/cyberfw/manager/platform_map.py +113 -0
  44. cyberfw-2.0.0/cyberfw/manager/plugins.py +324 -0
  45. cyberfw-2.0.0/cyberfw/manager/registry.py +190 -0
  46. cyberfw-2.0.0/cyberfw/manager/verify.py +143 -0
  47. cyberfw-2.0.0/cyberfw/motion.py +213 -0
  48. cyberfw-2.0.0/cyberfw/pipeline/__init__.py +49 -0
  49. cyberfw-2.0.0/cyberfw/pipeline/context.py +144 -0
  50. cyberfw-2.0.0/cyberfw/pipeline/engine.py +605 -0
  51. cyberfw-2.0.0/cyberfw/pipeline/executor.py +537 -0
  52. cyberfw-2.0.0/cyberfw/pipeline/processes.py +314 -0
  53. cyberfw-2.0.0/cyberfw/pipeline/schemas.py +417 -0
  54. cyberfw-2.0.0/cyberfw/pipelines/__init__.py +74 -0
  55. cyberfw-2.0.0/cyberfw/pipelines/loader.py +125 -0
  56. cyberfw-2.0.0/cyberfw/pipelines/recon_to_vuln.py +50 -0
  57. cyberfw-2.0.0/cyberfw/plugin.py +243 -0
  58. cyberfw-2.0.0/cyberfw/posture/__init__.py +8 -0
  59. cyberfw-2.0.0/cyberfw/posture/mail.py +349 -0
  60. cyberfw-2.0.0/cyberfw/posture/takeover.py +271 -0
  61. cyberfw-2.0.0/cyberfw/posture/tls.py +208 -0
  62. cyberfw-2.0.0/cyberfw/report/__init__.py +6 -0
  63. cyberfw-2.0.0/cyberfw/report/csv_report.py +41 -0
  64. cyberfw-2.0.0/cyberfw/report/diff.py +509 -0
  65. cyberfw-2.0.0/cyberfw/report/html_report.py +1993 -0
  66. cyberfw-2.0.0/cyberfw/report/json_report.py +85 -0
  67. cyberfw-2.0.0/cyberfw/report/run_info.py +52 -0
  68. cyberfw-2.0.0/cyberfw/report/sarif.py +87 -0
  69. cyberfw-2.0.0/cyberfw/resources.py +67 -0
  70. cyberfw-2.0.0/cyberfw/schedule.py +214 -0
  71. cyberfw-2.0.0/cyberfw/threatintel.py +319 -0
  72. cyberfw-2.0.0/cyberfw/tools/__init__.py +69 -0
  73. cyberfw-2.0.0/cyberfw/tools/ffuf.py +62 -0
  74. cyberfw-2.0.0/cyberfw/tools/gitleaks.py +94 -0
  75. cyberfw-2.0.0/cyberfw/tools/gowitness.py +118 -0
  76. cyberfw-2.0.0/cyberfw/tools/httpx_tool.py +28 -0
  77. cyberfw-2.0.0/cyberfw/tools/manifest.py +177 -0
  78. cyberfw-2.0.0/cyberfw/tools/manifest_tool.py +184 -0
  79. cyberfw-2.0.0/cyberfw/tools/naabu.py +35 -0
  80. cyberfw-2.0.0/cyberfw/tools/nmap.py +113 -0
  81. cyberfw-2.0.0/cyberfw/tools/nuclei.py +28 -0
  82. cyberfw-2.0.0/cyberfw/tools/rustscan.py +74 -0
  83. cyberfw-2.0.0/cyberfw/tools/subfinder.py +34 -0
  84. cyberfw-2.0.0/cyberfw/tools/targets.py +44 -0
  85. cyberfw-2.0.0/cyberfw/triage.py +217 -0
  86. cyberfw-2.0.0/cyberfw/ui.py +507 -0
  87. cyberfw-2.0.0/cyberfw/vt.py +323 -0
  88. cyberfw-2.0.0/pipelines/ports-to-vuln.yaml +29 -0
  89. cyberfw-2.0.0/pyproject.toml +107 -0
  90. cyberfw-2.0.0/registry.yaml +145 -0
  91. cyberfw-2.0.0/tests/conftest.py +149 -0
  92. cyberfw-2.0.0/tests/fixtures/.gitkeep +0 -0
  93. cyberfw-2.0.0/tests/integration/__init__.py +0 -0
  94. cyberfw-2.0.0/tests/integration/test_pipeline.py +88 -0
  95. cyberfw-2.0.0/tests/integration/test_real_tools.py +221 -0
  96. cyberfw-2.0.0/tests/unit/__init__.py +0 -0
  97. cyberfw-2.0.0/tests/unit/_cli.py +71 -0
  98. cyberfw-2.0.0/tests/unit/_dists.py +47 -0
  99. cyberfw-2.0.0/tests/unit/test_api.py +316 -0
  100. cyberfw-2.0.0/tests/unit/test_api_readme.py +39 -0
  101. cyberfw-2.0.0/tests/unit/test_archive.py +130 -0
  102. cyberfw-2.0.0/tests/unit/test_chromium.py +162 -0
  103. cyberfw-2.0.0/tests/unit/test_cli.py +3342 -0
  104. cyberfw-2.0.0/tests/unit/test_cli_package.py +79 -0
  105. cyberfw-2.0.0/tests/unit/test_cli_seams.py +60 -0
  106. cyberfw-2.0.0/tests/unit/test_completion.py +133 -0
  107. cyberfw-2.0.0/tests/unit/test_config.py +199 -0
  108. cyberfw-2.0.0/tests/unit/test_context.py +101 -0
  109. cyberfw-2.0.0/tests/unit/test_core_finish.py +200 -0
  110. cyberfw-2.0.0/tests/unit/test_core_layering.py +72 -0
  111. cyberfw-2.0.0/tests/unit/test_core_pipeline.py +287 -0
  112. cyberfw-2.0.0/tests/unit/test_core_steps.py +286 -0
  113. cyberfw-2.0.0/tests/unit/test_core_tool.py +130 -0
  114. cyberfw-2.0.0/tests/unit/test_core_workspace.py +89 -0
  115. cyberfw-2.0.0/tests/unit/test_diff.py +311 -0
  116. cyberfw-2.0.0/tests/unit/test_diff_coverage.py +102 -0
  117. cyberfw-2.0.0/tests/unit/test_engine.py +1412 -0
  118. cyberfw-2.0.0/tests/unit/test_executor.py +726 -0
  119. cyberfw-2.0.0/tests/unit/test_executor_buffered_failure.py +152 -0
  120. cyberfw-2.0.0/tests/unit/test_executor_lifecycle.py +212 -0
  121. cyberfw-2.0.0/tests/unit/test_export.py +97 -0
  122. cyberfw-2.0.0/tests/unit/test_github_client.py +499 -0
  123. cyberfw-2.0.0/tests/unit/test_gitleaks_inputs.py +97 -0
  124. cyberfw-2.0.0/tests/unit/test_hud.py +514 -0
  125. cyberfw-2.0.0/tests/unit/test_installer.py +727 -0
  126. cyberfw-2.0.0/tests/unit/test_live_view.py +375 -0
  127. cyberfw-2.0.0/tests/unit/test_local_tool_paths.py +109 -0
  128. cyberfw-2.0.0/tests/unit/test_lock.py +418 -0
  129. cyberfw-2.0.0/tests/unit/test_manager.py +556 -0
  130. cyberfw-2.0.0/tests/unit/test_manifest_format.py +187 -0
  131. cyberfw-2.0.0/tests/unit/test_manifest_tool.py +267 -0
  132. cyberfw-2.0.0/tests/unit/test_motion.py +388 -0
  133. cyberfw-2.0.0/tests/unit/test_pipeline_files.py +206 -0
  134. cyberfw-2.0.0/tests/unit/test_pipelines.py +32 -0
  135. cyberfw-2.0.0/tests/unit/test_platform_map.py +79 -0
  136. cyberfw-2.0.0/tests/unit/test_plugin_commands.py +447 -0
  137. cyberfw-2.0.0/tests/unit/test_plugin_contract.py +392 -0
  138. cyberfw-2.0.0/tests/unit/test_plugin_discovery.py +78 -0
  139. cyberfw-2.0.0/tests/unit/test_plugin_loading.py +299 -0
  140. cyberfw-2.0.0/tests/unit/test_plugin_tools.py +191 -0
  141. cyberfw-2.0.0/tests/unit/test_posture_mail.py +165 -0
  142. cyberfw-2.0.0/tests/unit/test_posture_takeover.py +164 -0
  143. cyberfw-2.0.0/tests/unit/test_posture_tls.py +94 -0
  144. cyberfw-2.0.0/tests/unit/test_process_tree.py +403 -0
  145. cyberfw-2.0.0/tests/unit/test_registry.py +175 -0
  146. cyberfw-2.0.0/tests/unit/test_report.py +478 -0
  147. cyberfw-2.0.0/tests/unit/test_resources.py +91 -0
  148. cyberfw-2.0.0/tests/unit/test_schedule.py +190 -0
  149. cyberfw-2.0.0/tests/unit/test_schemas.py +114 -0
  150. cyberfw-2.0.0/tests/unit/test_takeover_scope.py +129 -0
  151. cyberfw-2.0.0/tests/unit/test_threatintel.py +178 -0
  152. cyberfw-2.0.0/tests/unit/test_tool_adapters.py +526 -0
  153. cyberfw-2.0.0/tests/unit/test_triage.py +140 -0
  154. cyberfw-2.0.0/tests/unit/test_vt.py +177 -0
  155. cyberfw-2.0.0/tools.lock +286 -0
  156. cyberfw-2.0.0/wordlists/common.txt +264 -0
@@ -0,0 +1,62 @@
1
+ # Среда выполнения и кэш
2
+ __pycache__/
3
+ *.py[cod]
4
+ .venv/
5
+ .pytest_cache/
6
+ .mypy_cache/
7
+ .ruff_cache/
8
+ .coverage
9
+ .coverage.*
10
+ htmlcov/
11
+
12
+ # IDE / local editor state
13
+ .idea/
14
+ .vscode/
15
+
16
+ # Build and packaging artifacts
17
+ build/
18
+ dist/
19
+ *.egg-info/
20
+
21
+ # Динамические артефакты
22
+ tools_bin/
23
+ !tools_bin/.gitkeep
24
+ reports/
25
+ !reports/.gitkeep
26
+ logs/
27
+ !logs/.gitkeep
28
+ screenshots/
29
+ nuclei-templates/
30
+
31
+ # Конфиденциальные данные
32
+ .env
33
+ config.local.yaml
34
+
35
+ # Secrets and keys — never commit (this is a security tool)
36
+ *.key
37
+ *.pem
38
+ *.pfx
39
+ *.p12
40
+ id_rsa
41
+ id_rsa.*
42
+ id_ed25519
43
+ id_ed25519.*
44
+ *.ovpn
45
+
46
+ # Telegram bot runtime state (scan history DB)
47
+ *.sqlite3
48
+ bot-scans.sqlite3
49
+
50
+ # Local handoff / scratch files
51
+ PROGRESS.md
52
+ test_script
53
+
54
+ # Personal SSH-tunnel launcher (holds the key path + server IP)
55
+ /tunnel.bat
56
+
57
+ # Техническое задание (не публикуется)
58
+ тз/
59
+
60
+ # Системные файлы
61
+ .DS_Store
62
+ Thumbs.db
@@ -0,0 +1,489 @@
1
+ # Changelog
2
+
3
+ Формат — [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/), версии —
4
+ [SemVer](https://semver.org/lang/ru/). Изменения копятся в «Unreleased»; при
5
+ выпуске раздел получает номер и дату, а релиз на GitHub публикует его на PyPI.
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [2.0.0] — 2026-11-02
10
+
11
+ ### Changed
12
+ - Оркестрация прогона переехала из CLI в ядро `cyberfw/core/`: подготовка и
13
+ запуск пайплайна, одиночный `run`, проверки после скана, триаж, сравнение с
14
+ прошлым прогоном и запись отчётов. Ядро ничего не печатает и не спрашивает, а
15
+ сообщает о ходе работы событиями; CLI рисует их тем же текстом, что и раньше.
16
+ Это основа будущего публичного Python API.
17
+ - `cyberfw/cli.py` (~2850 строк) разрезан на пакет `cyberfw/cli/`: команды
18
+ разложены по модулям (`tools`, `scan`, `reports`, `triage`, `schedule`),
19
+ общие помощники — в `common`, отрисовка — в `views`, интерактивное меню — в
20
+ `launcher`. Код перенесён без изменений: команды, флаги, вывод, коды выхода и
21
+ порядок в `cyberfw --help` прежние; `python -m cyberfw.cli` работает.
22
+ - `cyberfw init` ставит инструменты из `tools.lock`: ровно залоченный релиз, а
23
+ архив сверяется с залоченным SHA-256 до того, как трогать прежнюю установку.
24
+ Новые релизы больше не приезжают сами — только через `cyberfw lock --upgrade`.
25
+ Инструменты, поставленные до lock-файла (без записанного хэша), один раз
26
+ перекачиваются и проверяются.
27
+ - Движок пайплайна выполняет независимые этапы параллельно. Зависимость этапа —
28
+ это его `input_from` (а если не задан — предыдущий этап по порядку); этапы без
29
+ ребра между ними (например `nmap` и `httpx` по одним и тем же открытым портам
30
+ naabu, или `nuclei`/`ffuf`/`gowitness` по живым хостам httpx) теперь идут
31
+ одновременно, а не друг за другом, — прогон ощутимо быстрее. Настройка
32
+ `concurrency` стала общим лимитом процессов **на все этапы сразу** (как и
33
+ обещал её docstring), а не только внутри одного fan-out. Итоговый результат
34
+ (узлы, записи, исключённые хосты) по-прежнему в порядке плана, так что прогон
35
+ воспроизводим независимо от того, как этапы переслоились.
36
+ - Поиск бинарника инструмента начинается с его каталога `tools_bin/<tool>/` и
37
+ только потом обходит весь `tools_bin/`: инвентарь в `status` и в меню больше
38
+ не перебирает сотни файлов Chromium ради каждого инструмента.
39
+
40
+ ### Added
41
+ - cyberfw публикуется на PyPI: `uv tool install cyberfw` или `pip install cyberfw`.
42
+ Релиз на GitHub собирает пакет и выкладывает его через trusted publishing,
43
+ без хранимого токена.
44
+ - Плагины инструментов. Пакет, установленный рядом с cyberfw, добавляет
45
+ инструменты через entry points: `cyberfw.tools` — адаптер на Python по
46
+ контракту `cyberfw.plugin` (версия 1), `cyberfw.manifests` — YAML-манифест,
47
+ который исполняет общий адаптер, без кода плагина. Установленный плагин
48
+ выключен, пока его не включить: `cyberfw plugins` показывает пакеты, их
49
+ инструменты и состояние (с причиной, если инструмент не работает),
50
+ `cyberfw plugins enable <пакет>` включает, `disable` выключает; выбор
51
+ хранится в `plugins.yaml`. Пакет с кодом включается только с `--allow-code`:
52
+ его код выполняется внутри cyberfw с доступом ко всему, что доступно
53
+ cyberfw. Коды выхода: `0` — включён, `1` — включён, но инструмент не
54
+ работает, `2` — не включён. Включённые инструменты работают в `run`,
55
+ пайплайнах, меню и дополнении по Tab; `status` и меню показывают, откуда
56
+ инструмент, а `status` — строку `plugins` со счётом по состояниям;
57
+ `report.json` записывает `tool_plugins` — пакет каждого плагинного
58
+ инструмента прогона. `cyberfw.api.list_plugins()` отдаёт то же данными.
59
+ - Публичный Python API `cyberfw.api`: `run_pipeline`, `plan_pipeline`, `run_tool`,
60
+ `load_run`, `compare_runs`, `export_sarif`, `export_csv` и их типы результатов
61
+ (`RunOutcome`, `Plan`, `SavedRun`), ошибка `PreflightError`. Ничего не печатает
62
+ и не спрашивает: результат — данными, ход прогона — через наблюдатель
63
+ `RunObserver`. Команды `pipeline`, `run`, `pipeline --plan`, `diff` и `export`
64
+ теперь работают через него. Описание — в README, раздел «Python API».
65
+ - `tools.lock` и `cyberfw lock [TOOLS...] [--upgrade]`: каждый скачиваемый
66
+ инструмент закреплён на одном релизе с SHA-256 ассета для linux/amd64,
67
+ linux/arm64, darwin/amd64, darwin/arm64, windows/amd64 и windows/arm64 (без
68
+ нативной сборки — x64 под эмуляцией на Windows on ARM и x86_64 под Rosetta на
69
+ Apple silicon). Хэш берётся из `digest` GitHub API или `checksums.txt` релиза
70
+ (при расхождении lock отказывает), а без них — скачиванием ассета.
71
+ `--upgrade` показывает «было → стало» и отклоняет релиз, у которого под тем
72
+ же тегом поменялись файлы. Запись помнит отпечаток правил выбора ассета:
73
+ правка `asset_patterns` делает её устаревшей, и `cyberfw lock` перерезолвит
74
+ её, а не поднимает тревогу о подмене. Lock лежит рядом с `registry.yaml` и
75
+ коммитится; wheel везёт его копию рядом с упакованным реестром.
76
+ - `cyberfw pipeline <name> --plan` — сухой прогон: печатает граф этапов (что из
77
+ чего получает), состояние инструмента каждого этапа, заданные у этапа опции
78
+ (severity/tags/rate/max) и вердикт готовности, затем выходит, ничего не
79
+ сканируя. Работает и без `--target`.
80
+ - Ванильный прогон `pipeline` показывает больше без флагов: в итоговой сводке
81
+ блок **Findings** — разбивка находок по severity, счётчики по категориям
82
+ (hosts/live/ports/services/secrets) и **Fix first** (самые важные находки
83
+ с целью и названием); в шапке живой карты/таблицы — пометка худшей severity
84
+ (`N vulns (M crit)`); а gowitness-скриншоты теперь включены по умолчанию,
85
+ когда могут отработать (инструмент установлен и найден Chrome/Chromium) —
86
+ иначе этап просто не добавляется, прогон не падает. Выключить —
87
+ `--no-gowitness`; `--gowitness` форсирует (как раньше, с префлайтом).
88
+ - Опции этапа в YAML-пайплайне: узел может задать `severity`, `tags`,
89
+ `rate_limit` (и `max_records`) прямо у себя. Опция этапа перекрывает общий
90
+ контроль (`--severity`/`--tags`/`--rate-limit`/настройки) для этого этапа;
91
+ этап без опции берёт общее значение — так в одном файле собирается «профиль»
92
+ скана. Валидируются как и прочие ключи (`rate_limit >= 1`, лишние ключи
93
+ отвергаются).
94
+ - Экспорт сохранённого прогона: `cyberfw export <run> --sarif | --csv [-o файл]`
95
+ читает `report.json` (id сессии / каталог / путь) и переводит без повторного
96
+ скана. `--sarif` — находки (nuclei, gitleaks, posture TLS/почта/takeover) в
97
+ SARIF 2.1.0 для GitHub code scanning / CI (severity → error/warning/note);
98
+ `--csv` — все записи таблицей (`tool, kind, severity, target, detail, muted`).
99
+ По умолчанию stdout, `-o` пишет файл; нужен ровно один формат. Новые модули
100
+ `cyberfw/report/sarif.py` и `cyberfw/report/csv_report.py`.
101
+ - Контроль скана (всё опционально, по умолчанию выключено — без флагов прогон
102
+ прежний): `--severity` / `--tags` → nuclei `-severity`/`-tags`; `--rate-limit N`
103
+ → предел запросов/сек в собственный флаг инструмента (nuclei/httpx `-rate-limit`,
104
+ naabu/ffuf `-rate`); `--exclude "<glob>"` (повторяемый у `pipeline`) → найденный
105
+ хост под glob не сканируется дальше (запись о находке остаётся), печатается
106
+ `scope: N host(s) excluded`, seed не трогается. `--severity/--tags/--rate-limit`
107
+ есть у `pipeline` и `run`. Настройки-эквиваленты: `severity`, `tags`,
108
+ `rate_limit`, `exclude` (через `CYBERFW_*` / `config.local.yaml`); флаг
109
+ перекрывает настройку на запуск.
110
+ - Локальные инструменты в реестре: запись с `source: local` (и опц. `path`)
111
+ описывает инструмент, который фреймворк не качает, а берёт из `PATH`
112
+ (ставит пользователь). `init` и автоустановка их пропускают; `status`
113
+ показывает `ready`/`not installed` по наличию в `PATH`, в колонке source —
114
+ `local`; пайплайн с отсутствующим локальным инструментом не стартует.
115
+ - `nmap` как локальный инструмент: определение сервисов и версий (`nmap -sV`)
116
+ по уже найденным открытым портам. Адаптер буферизует XML (`-oX -`, разбор
117
+ через `defusedxml`); встроенный `ports-to-vuln` получил этап `services`
118
+ (nmap по портам naabu, рядом с httpx). Новая зависимость — `defusedxml`.
119
+ - Мониторинг. `pipeline --alert [--alert-severity critical|high|medium|low]`
120
+ выходит с кодом `3` и печатает строку `ALERT: …`, когда по сравнению с прошлым
121
+ сохранённым прогоном той же цели появились новые находки не ниже порога
122
+ (дефолт `low`). Коды: `0` чисто, `1` упал этап (важнее алерта), `2` ошибка
123
+ аргументов (в т.ч. `--alert` с `--no-baseline`), `3` есть новое; первый скан
124
+ не алертит. Наружу ничего не шлётся — только код выхода и лог.
125
+ - `cyberfw schedule <pipeline> -t <target>` ставит такой скан на штатный
126
+ планировщик ОС: по умолчанию печатает запись под текущую систему (`crontab`
127
+ на Linux/macOS, `schtasks` на Windows), `--install` ставит, `--remove`
128
+ снимает (по имени `cyberfw-<pipeline>-<target>`). Частота — `--every
129
+ daily|weekly|hourly` + `--at HH:MM` или `--cron "…"` (только POSIX); флаги
130
+ скана пробрасываются; запись несёт `CYBERFW_ROOT_DIR` и пишет в
131
+ `logs/schedule.log`. Новый модуль `cyberfw/schedule.py`. Цель попадает в
132
+ команду, которую позже выполняет cron/schtasks, поэтому она ограничена
133
+ безопасным набором (буквы, цифры, `. _ - : /`), а все подстановки
134
+ экранируются (`shlex.quote` / `list2cmdline`) — чтобы цель не могла внедрить
135
+ команду в запись планировщика.
136
+ - Флаг `-v` / `--verbose` у `init`, `run`, `pipeline`, `status`: поднимает
137
+ уровень логов до `DEBUG` только для этого запуска и печатает трассировку
138
+ установки — разрешение релиза, URL и размер загрузок, выбранный под платформу
139
+ ассет, каталог распаковки и путь к бинарнику (для Chromium — платформу CfT,
140
+ версию и URL). Постоянный `log_level` не меняется.
141
+ - Автозагрузка portable Chromium (Chrome for Testing) для gowitness: `cyberfw
142
+ init` докачивает браузер в `tools_bin/chromium/`, если gowitness в наборе, а
143
+ системного Chrome нет. Скачанный Chromium имеет приоритет над системным,
144
+ виден в `cyberfw status` и передаётся gowitness через `--chrome-path`. Уже
145
+ имеющийся Chrome (системный или portable) повторно не качается (строка
146
+ `present`); платформа без сборки CfT помечается `skipped`. Пропустить —
147
+ `cyberfw init --no-chromium`.
148
+ - Живая таблица прогона: состояние каждого этапа, счётчик записей, прогресс
149
+ fan-out по целям, время этапа и причина падения обновляются на месте, под
150
+ ними — последние находки. Цвет записей отражает severity nuclei и класс
151
+ HTTP-кода. По завершении — панель-сводка (статус, записи по инструментам,
152
+ длительность, сессия, пути к отчётам).
153
+ - `PipelineEngine.set_stage_callback` — события жизненного цикла этапа
154
+ (`start` / `progress` / `done`) для внешних представлений.
155
+ - Единая таблица инвентаря для лаунчера и `status`: колонка версии, состояние
156
+ `ready` / `blocked` / `not installed` и сводка `N/M ready`; `init` печатает
157
+ результат таблицей.
158
+ - Пре-флайт `pipeline`: недоступные инструменты (`not installed` / `blocked`)
159
+ и отсутствующие жёсткие внешние зависимости (Chrome для gowitness)
160
+ называются до старта, команда выходит с кодом 2; `--force-start` запускает
161
+ всё равно. Необязательные зависимости (`nmap` для rustscan) выводятся
162
+ предупреждением и не мешают прогону. Упавший этап и зависящие от него `skipped` перечислены в сводке.
163
+ - `stage_timeout` (`CYBERFW_STAGE_TIMEOUT` / `config.local.yaml`): зависший
164
+ инструмент останавливается, этап помечается `failed`, pipeline идёт дальше.
165
+ - Pipeline из файла: любой `pipelines/<name>.yaml` запускается по имени и
166
+ появляется в лаунчере; пример `pipelines/ports-to-vuln.yaml`.
167
+ - `version:` в `registry.yaml` — пин релиза (теперь ограничение для
168
+ `cyberfw lock`); `init` пропускает уже установленную версию (`up to date`),
169
+ `init --force` переустанавливает.
170
+ - Блок провенанса в отчётах (`run` в JSON, таблица «Run» в HTML): pipeline,
171
+ seed, сессия, платформа, время и длительность, версии инструментов.
172
+ - `PipelineEngine.run_single` — публичный вход для одиночного запуска.
173
+ - Адаптеры несут свои подсказки и проверку цели (`target_prompt`,
174
+ `extra_input_prompt`, `validate_target`); `adapter_class(name)`.
175
+ - CI гоняет ubuntu × Python 3.10–3.14 плюс windows и macos; порог покрытия 80 %.
176
+ Dependabot для `uv.lock` и actions, `.pre-commit-config.yaml` (ruff + mypy).
177
+ - VirusTotal: `cyberfw vt <цель>` (домен, IP, URL или хэш; `--json` для
178
+ скриптов) и обогащение `pipeline` репутацией найденных доменов, IP и URL —
179
+ по умолчанию, со своим бесплатным ключом пользователя (`--no-vt` выключает,
180
+ `--vt-limit` ограничивает число запросов, 4 в минуту). Ключ ищется в
181
+ `CYBERFW_VT_API_KEY` / `.env` / `VT_API_KEY` / `VTCLI_APIKEY` / `~/.vt.toml`;
182
+ если его нет, интерактивный запуск один раз показывает, где его взять, и
183
+ сохраняет в `.env`. В HTML-отчёте у хостов появляется колонка репутации.
184
+ - Оценка опасности CVE: находки nuclei с CVE сверяются с CISA KEV
185
+ (эксплуатируется в реальных атаках, используется ransomware), EPSS
186
+ (вероятность атаки за 30 дней) и Exploit-DB (публичный эксплойт, модуль
187
+ Metasploit) и получают приоритет `fix now` / `fix soon`; в HTML — панель
188
+ «Fix first» и плитка «exploited». Ключи не нужны; KEV и Exploit-DB
189
+ кешируются на сутки в `cache_dir`. `--no-intel` выключает.
190
+ - Проверка TLS-сертификатов: httpx запускается с `-tls-grab`, и по уже
191
+ полученным сертификатам отчёт показывает инвентарь (срок, издатель, версия
192
+ протокола) и находки — истёк, истекает в ближайшие 7 / 30 дней,
193
+ недоверенный, выдан на другое имя, сервер умеет только TLS 1.1 и старше.
194
+ То, что уже нашли `ssl/`-шаблоны nuclei, не дублируется.
195
+ - Проверка подделки почты seed-домена: SPF, DMARC (`p`, `sp`, `pct`,
196
+ наследование от родительского домена, `redirect=`) и MX через
197
+ DNS-over-HTTPS, вердикт `protected` / `partial` / `spoofable` и находки с
198
+ рекомендациями; раздел «Email» в HTML. `--no-mail` выключает.
199
+ - Проверка захвата поддомена: у найденных поддоменов ищется «висящий» CNAME на
200
+ чужой сервис (GitHub Pages, Heroku, S3, Shopify, Azure, Elastic Beanstalk и
201
+ др.), ресурс на котором не занят и может быть перехвачен (severity high).
202
+ Для сервисов с wildcard-доменом признак — характерная строка на странице-
203
+ ошибке сервиса (один GET на его edge, не на origin цели), для Azure/EB —
204
+ NXDOMAIN цели. Фингерпринты из can-i-take-over-xyz; только CNAME-поддомены,
205
+ до 300 за прогон. `--no-takeover` выключает.
206
+ - Карточки находок в HTML показывают рекомендацию (`info.remediation`)
207
+ строкой «Fix:».
208
+ - Сравнение с прошлым сканом: `pipeline` находит в `reports/` самый свежий
209
+ прогон того же pipeline по той же цели и показывает, что изменилось, — новые
210
+ и исчезнувшие находки, поддомены, веб-сервисы, порты, пути, секреты; находку,
211
+ попавшую с тех пор в CISA KEV; смену HTTP-кода; продлённые сертификаты;
212
+ вердикт по почте; флаги VirusTotal. Раздел «Changes» и плитка в HTML, блок
213
+ `changes` в `report.json`, сводка в консоли. Отсутствие засчитывается только
214
+ если нужный инструмент отработал в обоих прогонах. `--baseline <сессия>` /
215
+ `--no-baseline`; `cyberfw diff <старый> <новый> [--json]` сравнивает любые
216
+ два сохранённых прогона.
217
+ - Триаж: приглушение находок (ложное срабатывание / принятый риск) правилами в
218
+ `triage.yaml` — `cyberfw mute <шаблон> [--target --reason --note --expires]`,
219
+ `cyberfw unmute <id>`, `cyberfw mutes`. Приглушённая находка показывается в
220
+ свёрнутом блоке «muted», не попадает в «Fix first», кольцо severity и плитку
221
+ findings (но остаётся в таблице записей и на карте хостов) и не считается
222
+ «новой» при сравнении с прошлым прогоном; при этом попадание приглушённой
223
+ уязвимости в CISA KEV всё равно сообщается. Правило сопоставляется по шаблону
224
+ (без учёта регистра, `*` — любой) и необязательной цели (fnmatch по хосту и
225
+ URL); истёкшие правила не применяются и называются в прогоне. Путь к файлу —
226
+ настройка `triage_file`.
227
+ - Шпаргалка по `?` в меню: клавиша `?` (или слово `help`) показывает карточку
228
+ с клавишами меню, расшифровкой каждой настройки и командами запуска из
229
+ терминала (`cstool status`, `cstool run`, `cstool pipeline recon-to-vuln`,
230
+ `diff`, `vt`, `mute`) — тем, чего в меню не видно. Карточка висит до Enter,
231
+ потом меню перерисовывается. В строке Keys появилась подсказка `? help`
232
+ (на достаточно широком окне).
233
+ - Tab в меню: в приглашении `» Select tool or action` Tab дописывает имя
234
+ инструмента или действия по первым буквам, а на пустой строке открывает
235
+ список всех вариантов с их клавишами и назначением (Tab / Shift+Tab / стрелки,
236
+ Enter). Имена принимаются наравне с клавишами (`nuclei` = `6`, `pipeline` =
237
+ `r`, `exit` = `q`). Вопрос `» Pipeline` дописывается так же, со списком этапов
238
+ каждого pipeline рядом, — его имя больше не нужно набирать целиком. Без
239
+ терминала ввод прежний. Новая зависимость — `prompt_toolkit`.
240
+
241
+ ### Changed
242
+ - Больше анимаций в консоли. Долгие шаги показывают живую строку активности
243
+ (`motion.Activity`): спиннер, бегущая полоса или — где известно, сколько
244
+ всего, — заполняющаяся со счётчиком и блеском, секундомер и пояснение; по
245
+ окончании строка исчезает, остаётся обычный результат. Она есть у скачивания
246
+ инструментов, проверки почты, захвата поддоменов (`N/всего` хостов), рейтинга
247
+ CVE, VirusTotal (`N/всего` — при лимите 4 запроса в минуту это минуты, а не
248
+ тишина) и у `cyberfw vt`. Меню при возврате «впечатывается» заново, как на
249
+ старте; «Goodbye.» проявляется из шума (`motion.decode`). Всё подчиняется
250
+ настройке `animations`; в пайпе и CI вывод не меняется. `vt.enrich` и
251
+ `takeover.scan` получили необязательный колбэк `progress`.
252
+ - Интерфейс открывается в чистом окне: launcher ставит зависимости и
253
+ докачивает инструменты (новая скрытая команда `cyberfw prepare`) в окне
254
+ запуска, а затем на Windows открывает интерактивное меню в новом окне
255
+ Windows Terminal (120×36, заголовок «CS-TOOL») — там интерфейс рисуется в
256
+ truecolor и с плавными анимациями, в отличие от старого conhost; окно
257
+ установки закрывается. Уже внутри Windows Terminal, без него или при
258
+ `CYBERFW_NO_WT=1` — в текущем окне на очищенном экране; на Linux/macOS — в том
259
+ же терминале на очищенном экране. В меню экран остаётся чистым: после
260
+ действия — пауза до Enter, затем меню сверху; Ctrl+C в меню — выход с кодом 0
261
+ (а не «Aborted!»), чтобы окно Windows Terminal закрывалось. Команды с
262
+ аргументами выполняются в текущем окне, как раньше. Очистка экрана при
263
+ возврате в меню теперь стирает и буфер прокрутки (`CSI 3J`), так что выше
264
+ не остаётся предыдущих кадров; на dumb-терминале и в пайпе/CI — как раньше.
265
+ - Терминальный интерфейс перерисован в едином «приборном» стиле: двойная
266
+ рамка с градиентом бренда, ярлыки секций в рамке, градиентная полоса
267
+ заголовка таблиц, клавиши-кейкапы, `■`-индикаторы состояния со словом.
268
+ Меню: таблица инструментов с колонкой `capability`, строки Keys и Settings;
269
+ карточка инструмента с состоянием, версией и источником; `status` — одна
270
+ панель из трёх секций; живая таблица прогона — в рамке с индикаторами
271
+ этапов; итоговая панель с полосами по инструментам, блоком Issues (этап и
272
+ причина падения) и путями, которые переносятся только по разделителям;
273
+ таблица записей `run` с колонкой severity и подсчётом в рамке. Для окон ниже
274
+ баннера с меню — компактная трёхстрочная шапка, и интро больше не
275
+ пропускается молча. Вопросы начинаются с `» `. Приглушённый текст теперь
276
+ серый `grey58` вместо `dim`, который классическая консоль Windows не рисует
277
+ (там Rich понижает его до `bright_black`).
278
+ - Анимации в терминале. Баннер появляется с интро: логотип проявляется из шума
279
+ слева направо, градиентная линия прорисовывается, квадратики инструментов
280
+ загораются по одному, счётчик готовых считает вверх. Живая таблица прогона
281
+ обновляется сама: спиннер у работающего этапа, полоса прогресса с бликом
282
+ (fan-out) или «сканер» (одиночный процесс), вспышка счётчика записей,
283
+ гаснущая метка `█▓▒░` у свежих находок. Карта топологии получила квадратик
284
+ на этап в шапке и «остывающую» подсветку новых хостов. `init` показывает
285
+ растущую таблицу и общий прогресс, итоговая панель досчитывает числа.
286
+ Отключается настройкой `animations: false` (`CYBERFW_ANIMATIONS`, клавиша
287
+ `a` в меню); в пайпе, CI и на «тупом» терминале выводится только финальный
288
+ кадр, как раньше. Глифы — из кодовой страницы 437, их рисуют Consolas и
289
+ Lucida Console; брайлевский спиннер карты заменён на полублочный `▀▐▄▌`.
290
+ - HTML-отчёт переделан в анимированный дашборд: шапка с радаром найденных
291
+ хостов, плитки KPI со счётчиками, диаграмма severity, записи по
292
+ инструментам, распределение HTTP-кодов, граф pipeline с учётом `input_from`,
293
+ сводка по хостам, карточки уязвимостей и секретов, галерея скриншотов
294
+ gowitness и таблица записей с поиском, фильтром по инструменту и сортировкой.
295
+ Тёмная/светлая тема с переключателем, версия для печати; анимации уважают
296
+ `prefers-reduced-motion`, без JavaScript отчёт виден целиком.
297
+ Content-Security-Policy допускает только собственные скрипты отчёта (по
298
+ хэшу), поэтому данные сканирования не могут выполниться как код.
299
+ - Баннер: вместо строки «Integrated Cybersecurity Framework · v1.0.0» —
300
+ градиентная линия и полоса состояния с `▰` на каждый инструмент (цвет по
301
+ `ready` / `blocked` / `not installed`), счётчиком готовых, платформой и
302
+ версией.
303
+ - Сохранение результата стало выбором пользователя: по окончании `run` и
304
+ `pipeline` спрашивают, сохранять ли отчёт. «Нет» удаляет каталог сессии,
305
+ созданный этим прогоном (ранее существовавший не трогается). Ответ можно
306
+ задать заранее: `--save`/`--no-save` и `--report`/`--no-report`; без TTY
307
+ вопроса нет и поведение прежнее. Одиночный `run` теперь тоже пишет
308
+ `report.json` и `report.html`, а не только JSONL.
309
+ - Каждый инструмент ставится в `tools_bin/<tool>/`; архив удаляется после
310
+ распаковки, каталог инструмента очищается при переустановке, старые архивы
311
+ и бинарники плоской раскладки убираются.
312
+ - Лаунчер: номера инструментов `1..N` от реестра, pipeline на `r`, выход `0`/`q`.
313
+ - Context Store держит файл этапа открытым на время этапа (flush после каждой
314
+ записи) вместо open/close на каждую запись.
315
+ - При отмене дочернему процессу даётся 3 с на выход по SIGTERM, затем SIGKILL;
316
+ ошибки называют сигнал («crashed with SIGSEGV») или NTSTATUS-код на Windows.
317
+ - Известный, но не установленный инструмент — это `failed`-этап, а не обрыв
318
+ всего прогона без отчёта.
319
+
320
+ ### Removed
321
+ - Ключи `sha256:` и `needs_checksum:` в `registry.yaml`: целостность теперь
322
+ обеспечивает `tools.lock`, и проверяется каждый залоченный ассет. Старые
323
+ ключи не ломают загрузку реестра — они игнорируются с предупреждением.
324
+
325
+ ### Fixed
326
+ - Обновление инструмента удаляло рабочую версию до того, как новая была
327
+ распакована: повреждённый архив, архив без исполняемого файла, превышение
328
+ лимита распаковки или сетевой сбой оставляли без инструмента и без записи о
329
+ его версии. Теперь новая версия распаковывается и проверяется рядом со старой
330
+ и встаёт на её место только целиком; при любом сбое — и при неудачной замене —
331
+ остаются прежний инструмент и его запись, а запись пишется атомарно. Прерванная
332
+ замена (Ctrl+C, сбой) тоже возвращает прежнюю версию — сразу или при следующей
333
+ установке, — а незаконченные копии рядом с ней (`.<tool>.staging-*`,
334
+ `.<tool>.previous-*`) никогда не принимаются за установленный инструмент.
335
+ - `CYBERFW_ROOT_DIR` и `Settings(root_dir=...)` меняли каталоги отчётов и
336
+ инструментов, но `registry.yaml` и `tools.lock` по-прежнему брались из
337
+ текущего каталога — то есть из другого workspace. Теперь первым ищется
338
+ registry того workspace, который называют настройки, и lock лежит рядом с ним;
339
+ у workspace без своего registry — поставляемый с cyberfw (в клоне — из
340
+ репозитория, при установке из wheel — из пакета) и lock рядом с ним.
341
+ - Сравнение с прошлым прогоном выбирало baseline по одному имени хоста: для
342
+ пайплайна, начинающегося с nuclei или httpx, прогон
343
+ `https://example.com:8443/admin` сравнивался с прогоном
344
+ `http://example.com:8080/other` — и находки непроверенного сервиса
345
+ числились исправленными. Теперь значит то, что сканирует первый этап:
346
+ у subfinder, naabu и rustscan — хост, у nmap — хост и порт, у остальных —
347
+ весь URL (схема, хост, порт, путь); регистр хоста, порт по умолчанию и
348
+ завершающий `/` не различаются.
349
+ - Имя этапа в YAML-пайплайне становилось частью пути: этап `../outside`
350
+ записывал свой `.input` вне каталога сессии, а имена, различающиеся только
351
+ `/`, пробелом или `_`, писали в один и тот же файл. Теперь имя этапа должно
352
+ быть простым — без `/`, `\` и `:`, не `.` и не `..`; пайплайн с таким
353
+ именем или с двумя этапами, чьи файлы совпали бы, отклоняется до запуска, а
354
+ файлы этапа всегда лежат в каталоге сессии.
355
+ - `--exclude` не действовал на обогащение VirusTotal: исключённые хосты всё
356
+ равно отправлялись в VirusTotal. Теперь туда уходят только хосты в области
357
+ сканирования, как и в takeover-проверку; записи обнаружения остаются в отчёте.
358
+ - Таймаут, отмена или ошибка обработчика останавливали только процесс,
359
+ запущенный cyberfw, а то, что он сам запустил (обёртка и её сканер,
360
+ gowitness и Chrome, воркеры), продолжало работать. Теперь каждый инструмент
361
+ идёт в своей группе процессов — отдельная сессия на POSIX, Job Object на
362
+ Windows — и останавливается вся группа: на POSIX сначала SIGTERM всем, после
363
+ паузы SIGKILL. То, что инструмент оставил работать после своего выхода, тоже
364
+ завершается. Сигналы, которые завершают cyberfw (SIGTERM, SIGHUP, SIGQUIT —
365
+ `kill`, `timeout`, закрытый терминал, Ctrl+\), сперва останавливают его
366
+ инструменты, а Ctrl+Z приостанавливает их вместе с cyberfw; сигнал, который
367
+ велено игнорировать (`nohup`), по-прежнему игнорируется.
368
+ - На macOS с Python 3.14 до 3.14.10 приостановленный инструмент (Ctrl+Z или
369
+ чужой SIGSTOP) мог заморозить cyberfw: asyncio там принимал остановку
370
+ процесса за его выход и ждал его завершения, а сигналы до cyberfw не доходили
371
+ (python/cpython#158287). На этих версиях cyberfw ждёт выхода инструмента
372
+ сам — через `waitpid()`, на который остановка не действует.
373
+ - Этап ждал бесконечно, если инструмент вышел, а оставленный им процесс держал
374
+ его вывод открытым. Теперь такой процесс получает 3 секунды после выхода
375
+ инструмента и завершается вместе с его группой.
376
+ - Этап, читающий другой этап, запускался на исходной цели, если тот ничего
377
+ не нашёл или всё найденное отсёк `--exclude`: после naabu без портов httpx
378
+ сканировал seed, после пустого httpx — nuclei. Теперь исходную цель
379
+ получает только корневой этап; этапу без входов сканировать нечего — его
380
+ инструмент не запускается, а сам этап считается отработавшим с 0 записей.
381
+ - Строка вывода, которую не принимает схема инструмента (например, порт
382
+ строкой вместо числа у naabu), роняла весь этап вместе с уже найденными
383
+ записями. Теперь такая строка отбрасывается и попадает в сводку «did not
384
+ match the expected schema», как строки не в JSON; этап идёт дальше.
385
+ - Два прогона, начатые в одну секунду (скрипт по списку целей, параллельные
386
+ задачи CI), получали одну сессию: второй перезаписывал отчёт первого и
387
+ дописывал свои записи в его JSONL. Новая сессия больше не занимает чужую
388
+ папку — при совпадении к её id добавляется `-2`, `-3`…
389
+ - Сломанный или отсутствующий `registry.yaml` завершал `pipeline`,
390
+ `pipeline --plan` и `run` трассировкой Python; теперь — сообщением об ошибке
391
+ реестра (код 2 у `pipeline`, 1 у `run`).
392
+ - Предупреждения проверок после скана (почта, threat intel, VirusTotal) теряли
393
+ часть текста ошибки в квадратных скобках: Rich принимал её за разметку.
394
+ Теперь текст показывается как есть.
395
+ - То же было и с остальными сообщениями CLI: ошибки движка, реестра, проверки
396
+ инструмента, установки, `cyberfw lock` и записи отчёта, ошибка и категории
397
+ VirusTotal, причина провала `run`, а также неверное значение `--session`,
398
+ `--reason`, `--cron` или имени инструмента в `lock` печатались через разметку
399
+ Rich, и `[...]` в них пропадало («the engine [broke]» → «the engine »; у
400
+ `--cron` ещё и оставалась лишняя `\`). Сырые строки инструментов под
401
+ `--no-parse` теперь выводятся ровно так, как их напечатал инструмент: без
402
+ разметки и без замены `:ok:` на эмодзи.
403
+ - Запланированный скан не запускался, если `cyberfw` нет в PATH: тогда
404
+ `cyberfw schedule` записывает в задание `python -m cyberfw …`, а у пакета не
405
+ было `__main__.py`. Теперь `python -m cyberfw` запускает тот же CLI — в том
406
+ числе в заданиях, записанных раньше.
407
+ - RustScan на x86_64 Linux (в т.ч. WSL) получал aarch64-сборку: запасной поиск
408
+ по шаблонам реестра смотрел на ОС, но не на архитектуру, а RustScan называет
409
+ ассеты «арх-ОС» и перечисляет aarch64 первым. Теперь шаблоны чужой
410
+ архитектуры не используются, а Linux ARM никогда не откатывается на x64.
411
+ - Узкие окна. Карточка инструмента уже ~60 колонок печатала описание по
412
+ слову или по букве в строке, а строки вылезали за рамку: панели, стоящие
413
+ рядом, теперь встают друг под другом, если общей остаётся меньше 24 клеток,
414
+ и каждая строка тела ровно по ширине рамки. Шапка уже ~78 колонок резала
415
+ логотип многоточиями и теряла счётчик `N/M ready`: теперь сначала убирается
416
+ `UTM`, потом логотип, а строка состояния переносится только между частями.
417
+ Итоговая сводка на 42 колонках и уже теряла число записей по инструментам:
418
+ полоса сужается под окно и убирается, если на неё не осталось места.
419
+ - Та же сводка на 36–40 колонках под rich 13.x (разрешён `rich>=13.7`)
420
+ по-прежнему теряла счётчики: rich 13 прибавлял к `min_width` колонки имён
421
+ отступ края таблицы, которого в сетке нет, и таблица выходила на клетку
422
+ шире расчёта. Имена теперь выравниваются без `min_width`, и раскладка
423
+ одинакова в rich 13 и 15.
424
+ - CJK, эмодзи и комбинируемые диакритики в ярлыке, подписи или подвале рамки
425
+ (`cyberfw pipeline recon-to-vuln -t 例え.jp`) сдвигали или срезали угол
426
+ `╗`/`╝`: текст в рамке раскладывается по клеткам экрана.
427
+ - Ярлыки, подписи и подвал затирали стыки `╤`/`╧` соседних панелей. Ярлык,
428
+ которому мешает стык, переезжает за него, а подпись или подвал, которые
429
+ накрыли бы стык, не рисуются.
430
+ - Лид-ин `» ` у вопросов был без цвета: `Prompt` и `Confirm` спрашивали через
431
+ глобальную консоль Rich, у которой нет темы приложения.
432
+ - Финальный кадр живой таблицы в низком терминале обрезал последние находки
433
+ (при высоте 12 строк оставалось 3 из 8), а с `--no-report` они больше нигде
434
+ не выводятся. Завершённый кадр теперь печатается целиком.
435
+ - Ярлыки проваленного прогона в 16 цветах были чёрными по тёмно-красному
436
+ (контраст около 2:1 на классической консоли Windows): градиент теперь
437
+ начинается с ярко-красного.
438
+ - Приглушённый текст (`bright_black`) пропадал в Solarized Dark, где цвет 8
439
+ совпадает с фоном. Теперь это серый `grey58` (246 в 256 цветах); на
440
+ классической консоли Windows Rich сам понижает его до `bright_black`.
441
+ - В неинтерактивном выводе (пайп, CI) строка после живой таблицы прогона
442
+ приклеивалась к её последней строке.
443
+ - Записи gowitness v3 теряли имя скриншота и HTTP-код: v3 пишет `file_name` и
444
+ `response_code`, а схема ждала `filename` и `status_code`. Теперь читаются
445
+ оба варианта.
446
+ - Этап падал с `Separator is not found, and chunk exceed the limit`, если
447
+ инструмент печатал одну строку stdout длиннее 64 КиБ (лимит ридера asyncio
448
+ по умолчанию) — например крупная находка `nuclei -jsonl`. Лимит поднят до
449
+ 8 МиБ, а строка сверх него теперь отбрасывается с предупреждением, не убивая
450
+ этап.
451
+ - Windows: инструменты-скрипты с shebang не запускались, если bash находился
452
+ как `Git\bin\bash.exe` (так его видят PowerShell и раннер GitHub) — путь
453
+ конвертировался по WSL-схеме `/mnt/c/...`, и Git Bash отвечал
454
+ `No such file or directory` (exit 127). Теперь `cygpath` ищется и в соседнем
455
+ `usr\bin`, а без него схема выбирается по тому, какой bash найден:
456
+ `/mnt/c/...` только для WSL-шима, `/c/...` для MSYS/Git.
457
+ - naabu получал URL целиком (`-host https://999.md`) и падал с `no valid ipv4
458
+ or ipv6 targets were found`; теперь и seed, и цели предыдущего этапа
459
+ приводятся к имени хоста — общий `cyberfw/tools/targets.hostname_of`,
460
+ которым пользуется и rustscan.
461
+ - Этап, чей источник упал, больше не подставляет seed вместо результатов
462
+ этого источника (httpx сканировал сам seed и рапортовал успех).
463
+ - `Settings.max_archive_size` не доходил до установщика (читался приватный
464
+ `CYBERFW_MAX_ARCHIVE`).
465
+ - `UnicodeEncodeError` при перенаправлении вывода на Windows (`status > out.txt`,
466
+ `init | tee`): не-UTF-8 stdout/stderr переконфигурируются в UTF-8.
467
+ - Три Windows-ориентированных теста падали на Linux-раннере CI.
468
+ - `append_raw` в Context Store не закрывал файл.
469
+
470
+ ### Security
471
+ - Инструменты больше не получают всё окружение cyberfw. Процесс инструмента
472
+ видит только то, что нужно любой программе (`PATH`, домашний и временные
473
+ каталоги, системные каталоги Windows, прокси, сертификаты, локаль), и
474
+ переменные, перечисленные в его записи `registry.yaml` под новым ключом
475
+ `env:`. Токен GitHub, ключ VirusTotal и прочие секреты из окружения до
476
+ скачанных бинарников больше не доходят. Если инструменту нужна своя
477
+ переменная (например, `PDCP_API_KEY` для nuclei), добавьте её в `env:`.
478
+ - Секреты, найденные gitleaks, по умолчанию маскируются: gitleaks запускается с
479
+ `--redact`, а адаптер ещё и заменяет значение на `REDACTED` при разборе, так
480
+ что живой ключ не попадает ни в JSONL сессии, ни в `report.json`/`report.html`.
481
+ Сырые значения — `cyberfw run gitleaks --show-secrets` или настройка
482
+ `redact_secrets: false` (`CYBERFW_REDACT_SECRETS=false`).
483
+
484
+ ## [1.0.0] — 2026-09-21
485
+
486
+ Первая версия: кроссплатформенный CLI для установки прекомпилированных
487
+ инструментов из GitHub Releases и их оркестрации (subfinder, naabu, httpx,
488
+ nuclei, ffuf, rustscan, gitleaks, gowitness), pipeline `recon-to-vuln`,
489
+ интерактивный лаунчер, JSON/HTML-отчёты, checksum-верифицированный bootstrap uv.
cyberfw-2.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daniil Sirbu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.