A self-hosted, single-operator network reconnaissance and exploitation console. Kroft wraps three things behind one dark-themed web UI:
- nmap — for asset discovery and service/OS fingerprinting.
- Metasploit Framework (via its RPC daemon,
msfrpcd) — for module search, exploitation, post-exploitation, session handling, and an interactive console. - OpenVAS / Greenbone (via GMP) — an authenticated vulnerability scanner that finds CVE-backed weaknesses on discovered hosts and feeds them into the asset inventory, engagement reports, and Kroft.AI's attack planning.
- Kroft.AI — an in-browser LLM advisor (backed by Ollama) that reads your recon data and the OpenVAS findings, suggests real, verified MSF modules, explains output, and can run a guided autonomous "autopilot" loop.
Everything an engagement produces — discovered hosts, exploit attempts, captured loot — is stored in a local SQLite database so it survives restarts and can be exported.
⚠️ Authorized use only. Kroft is built for security testing of systems you own or are explicitly authorized to assess. A configurable scope guardrail blocks intrusive actions against out-of-scope hosts, but it is a safety net, not a substitute for authorization.
- Features
- Architecture
- Project structure
- How it works
- Setup
- Configuration
- API reference
- Security notes
- Development
The UI is a single page with ten tabs, each backed by a slice of the API:
| Tab | What it does |
|---|---|
| Asset Matrix | The host inventory. Lists every discovered host with ports, OS guess, MAC, tags, last-seen time, and a vulnerability badge (count + max CVSS from OpenVAS). Supports tagging, deletion, CSV/JSON export, and a one-click "run vuln scan" action per host. |
| Advanced Scanner | Launches nmap scans with an allow-listed set of flags. Scans run in the background; progress is polled. |
| Vuln Scanner | Launches OpenVAS / Greenbone scans against a target (scope-guarded, background job with live phase/progress). Findings land in a severity-ranked table with CVSS, CVE links, and remediation, and can be handed to Kroft.AI ("Analyze with AI" / per-finding "find exploits"). |
| Findings & Loot | Credentials, hashes, keys, and other findings, de-duplicated and attributable to a host/source. |
| Pentest Console | Search MSF exploit modules, inspect their options/payloads, and dispatch them at a target. |
| Active Shells | Lists live shell/meterpreter sessions and lets you run commands in them. |
| Kroft.AI | An LLM advisor + autonomous agent. Grounds its suggestions in real modules via the suggest/validate endpoints, can execute MSF command blocks, and analyzes the output. |
| Cyberspace | A 3D, real-time visualization of the engagement (three.js): your network floats as glowing nodes around the Kroft core, the AI agent buzzes between them scanning/exploiting, owned hosts turn green and pivot, and DB activity streaks packets to/from the core. Includes a scrubbable timeline to replay everything. Purely cosmetic — a window onto the real tools. |
| Post / Auxiliary Console | Runs post and auxiliary modules and captures their output. |
| MSF Console | A full interactive msf6 > terminal in the browser (xterm.js). |
Supporting capabilities: CVE enrichment (NVD lookups for a product/version), OpenVAS vulnerability findings woven into the matrix / reports / AI context, engagement scope enforcement, and persistent storage of all of the above.
Kroft is a Flask application organized in three layers, plus background workers and the external services it orchestrates.
Browser (single-page UI, Tailwind + xterm.js)
│ fetch() / JSON
│ (Kroft.AI talks to Ollama directly)
┌──────────────────────────────────────┼───────────────────────────────────┐
│ Flask app (kroft/) ▼ │
│ │
│ ROUTES (kroft/routes/*) ── thin HTTP handlers, one blueprint/domain │
│ main · hosts · scans · settings · loot · reports · cve · ollama │
│ openvas · msf/{status,modules,exploit,sessions,console} │
│ │ │
│ ▼ │
│ SERVICES (kroft/services/*) ── the heavy lifting │
│ nmap_scanner · msf_client · msf_console · msf_modules · msf_workers │
│ gvm_client · openvas_scanner │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ CORE (kroft/*) background threads MSF RPC client GVM/GMP │
│ database/models (run_scan, (auto-reconnect) client │
│ state (registries) run_exploit, run_openvas_scan │
│ settings_store run_post_module) │
│ scope │
└───────────────────────────────────────────────────────────────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
SQLite (kroft_assets.db) nmap binary msfrpcd (MSF RPC) openvas (GVM/GMP)
Design principles
- Routes stay thin. Each blueprint just validates input and calls a service; it never embeds business logic.
- Services own one concern each. All Metasploit RPC quirks, nmap argument
handling, and worker logic live in
kroft/services/, isolated and testable. - Long-running work runs off-thread. Scans and exploits are dispatched to
daemon threads that record progress in in-memory registries; the UI polls for
status. The HTTP request returns immediately with a
job_id. - The MSF connection is managed centrally. One background thread keeps the RPC
connection alive; everything else calls
get_msf()to grab a live client (orNone) without ever blocking. - An application factory (
create_app()) builds and wires everything, so the app is import-safe and easy to configure.
.
├── app.py # Entry point: create_app().run() (Docker CMD targets this)
├── kroft/ # The application package
│ ├── __init__.py # create_app() application factory
│ ├── config.py # Env-driven configuration (DB, MSF, OpenVAS/GVM, Ollama, server)
│ ├── database.py # SQLAlchemy engine, Session factory, init_db() + migrations
│ ├── models.py # ORM models: Host, ExploitLog, Loot, Vulnerability, Setting
│ ├── settings_store.py # get_setting / set_setting (key-value store)
│ ├── state.py # In-memory registries + locks (jobs, sessions, consoles)
│ ├── scope.py # Engagement scope guardrail (in_scope)
│ ├── events.py # In-memory ring buffer of activity events (for the visualizer)
│ ├── activity.py # after_request hook: maps DB/action routes -> events
│ ├── services/ # Service layer — the heavy lifting
│ │ ├── nmap_scanner.py # nmap arg allow-list, conflict resolution, port-merge, run_scan worker
│ │ ├── msf_client.py # auto-reconnecting MSF RPC connection manager + get_msf()
│ │ ├── msf_console.py # safe wrappers around the msfrpcd console API + banner stripping
│ │ ├── msf_modules.py # module search / validate / suggest, compatible payloads
│ │ ├── msf_workers.py # run_exploit + run_post_module background workers
│ │ ├── gvm_client.py # OpenVAS/GVM connection manager + gmp_session() helper
│ │ └── openvas_scanner.py # run_openvas_scan worker: GMP scan lifecycle + report parsing
│ └── routes/ # HTTP layer — one Flask blueprint per domain
│ ├── __init__.py # register_blueprints(app)
│ ├── main.py # GET / (serves the UI)
│ ├── hosts.py # /api/hosts* (inventory, tags, export)
│ ├── scans.py # /api/scan, /api/jobs (nmap dispatch + status)
│ ├── settings.py # /api/settings
│ ├── loot.py # /api/loot*
│ ├── reports.py # /api/report/<ip>
│ ├── cve.py # /api/cve (NVD enrichment)
│ ├── openvas.py # /api/openvas/* (vuln scan dispatch, status, findings)
│ ├── ollama.py # /api/ollama/models
│ ├── events.py # /api/events (visualizer event feed)
│ └── msf/ # /api/msf/* grouped by concern
│ ├── __init__.py # shared `bp` blueprint
│ ├── status.py # status + db_nmap scan
│ ├── modules.py # search / suggest / validate / info
│ ├── exploit.py # exploit & post/aux dispatch, jobs, output, logs
│ ├── sessions.py # session list / exec / read / kill
│ └── console.py # console_exec + interactive console
├── templates/ # Server-rendered HTML (Jinja2)
│ ├── index.html # Page shell: <head> + {% include %}s + ordered <script> tags
│ └── partials/ # HTML components, assembled by index.html
│ ├── _styles.html # the Tailwind <style> block (kept inline for the CDN JIT)
│ ├── _sidebar.html # left-hand navigation
│ ├── _header.html # top bar (title, scope indicator, settings)
│ ├── tabs/ # one file per tab: _matrix, _scanner, _pentest, _shells,
│ │ # _msfconsole, _kroftai, _cyberspace, _postaux, _findings, _openvas
│ └── modals/ # _settings, _report, _job_detail
├── static/ # Browser assets served at /static
│ └── js/ # Front-end logic, split by feature, loaded in order
│ ├── 01-core.js # globals, clock, tab switching
│ ├── 02-scanner.js # nmap scanner + jobs queue
│ ├── 03-matrix.js # asset matrix
│ ├── 04-pentest.js # pentest console + "Hail Mary"
│ ├── 05-shells.js # shells / xterm terminals
│ ├── 06-kroftai.js # Kroft.AI: status, chat, analysis
│ ├── 07-ai-commands.js # AI command blocks + job-output injection
│ ├── 08-postaux.js # post/aux panel, job-detail modal, post/aux console
│ ├── 09-console.js # interactive MSF console + Ollama model picker
│ ├── 10-findings.js # findings/loot, settings/scope, report
│ ├── 11-extras.js # notifications, cred reuse, auto post-recon, CVE
│ ├── 12-autopilot.js # autonomous agent loop
│ ├── 13-init.js # bootstrap calls on page load
│ ├── 14-cyberspace.js # 3D visualizer: recorder, scene, choreography, playback
│ └── 15-openvas.js # Vuln Scanner tab: launch/poll scans, findings table, AI hand-off
├── kroft_assets.db # SQLite database (created/updated at runtime)
├── requirements.txt # Python dependencies
├── Pipfile # Pipenv equivalent of requirements
├── Dockerfile # Builds the scanner image (installs nmap + deps)
└── docker-compose.yml # Runs the scanner + Metasploit RPC + OpenVAS containers together
Five SQLite-backed tables hold everything persistent:
Host— one row per discovered asset: IP, MAC, hostname, OS guess, open ports (both a human-readable string and structured JSON), status, last-seen, user tags, and an OpenVAS rollup (vuln_count,max_severity).ExploitLog— an audit trail: every exploit/auxiliary/post run with its module, options, status, result, and any resulting session id.Loot— findings (credentials, hashes, keys, etc.), de-duplicated on(host_ip, type, value).Vulnerability— OpenVAS/Greenbone findings: NVT name + OID, port, severity/CVSS/threat, CVE IDs, description, remediation, and the report id. De-duplicated on(host_ip, oid, port)so re-scans refresh rather than pile up.Setting— a key/value store; today its main job is the engagementscope_cidr.
init_db() creates the tables on startup and runs tiny migrations that add the
tags, vuln_count, and max_severity columns to older hosts tables.
A scan request returns a job_id immediately and the work happens in a daemon
thread (run_scan):
- Sanitize user flags.
sanitize_args()tokenizes the input and checks each token (and its value, for flags like-p 80) againstALLOWED_ARG_PATTERN. Anything not on the allow-list is dropped and reported as a warning — raw flags are never passed to nmap. - Resolve conflicts. Mutually exclusive flags (e.g. a ping-sweep
-snalongside-sV) are pruned. - Scan and persist. Discovered hosts are upserted with merge, not clobber
semantics: a narrow follow-up scan never erases OS/port/version data a broader
earlier scan gathered (
merge_ports).
Kroft drives a real Greenbone/OpenVAS scanner over GMP — it does not re-implement scanning. Like the MSF integration, it degrades gracefully when the scanner is down or still syncing feeds.
gvm_client.pyowns the connection. A background thread health-checks GMP every 20s (get_gvm_status()caches{connected, version}for the UI). Work runs throughgmp_session(), a context manager that opens a fresh, authenticated TLS session per unit of work — deliberately short-lived so a multi-minute scan can't be killed by an idle-dropped socket. All imports are deferred so the app boots even ifpython-gvmisn't installed.openvas_scanner.pyruns the scan lifecycle in a daemon thread (run_openvas_scan): create target → create task → start → poll to completion (updatingopenvas_jobs[job_id]with live phase + progress) → fetch the report.parse_report()defensively pulls each finding's NVT name/OID, port, severity/CVSS/threat, CVE refs and remediation;persist_vulns()de-dupes on(host_ip, oid, port)and rolls the counts up onto theHostrow (creating a stub host if the asset was only ever seen by the vuln scan). A compactsummarize_vulns()string is stored on the job for the job-detail view and the Kroft.AI hand-off.
How the findings make everything else smarter
- Asset Matrix shows a severity badge (count + max CVSS) per host.
- Engagement reports (
/api/report/<ip>) include the vulnerabilities array, and the report writer is prompted to add a dedicated OpenVAS section. - Kroft.AI folds the findings into its recon context: before an analysis,
loadHostVulns()primes a per-host cache andbuildReconContext()lists the scanner-confirmed vulnerabilities (with CVEs) so the model prioritises real weaknesses over version-banner guesses. Per-finding "find exploits" and the tab-level "Analyze with AI" button pivot straight into a targeted MSF-module ask.
This is the most defensively written part of the app, because msfrpcd and the
pymetasploit3 client occasionally return a bare bool where a dict/list is
expected — which otherwise crashes deep inside the library with
"'bool' object is not subscriptable". Kroft sidesteps this throughout:
msf_client.pyruns one background thread that connects tomsfrpcd, health-checks it every 10s by readingcore.version, and reconnects on failure. Callers useget_msf()to get a live client instantly orNone— they never block.msf_console.pycalls the console RPCs directly and validates each response shape, instead of going throughmsf.consoles.console()(whose manager subscripts an unvalidated response on every call). It also strips the noisy Metasploit startup banner before output is shown or fed to the AI.msf_modules.pyvalidates that a module is loadable before handing its name tomodules.use(), and provides "did you mean" suggestions for bad module paths by searching the live module DB.msf_workers.pyruns exploits and post/auxiliary modules in daemon threads:run_exploitvalidates the module, sets options, auto-selectsLHOST(the routable IP toward the target) and the best compatible payload (handling bind-shell-only modules specially), executes via the low-level module manager to avoid the library's payload-validation crash, then polls up to 30s for a new session.run_post_moduledrives a console (use→set …→run -j), polls for output, strips the banner, and records the result.
Exploit/auxiliary/post dispatch is intentionally routed by module type:
auxiliary and post modules must not be loaded as exploit/..., so the exploit
endpoint detects those prefixes and sends them to the console-based worker.
Live activity that doesn't belong in the database lives in process-wide registries
guarded by locks: active_jobs (scans), exploit_jobs (exploit/aux/post),
msf_sessions (open sessions), and msf_consoles (interactive terminals). The UI
polls the corresponding endpoints to render real-time status.
The AI advisor runs in the browser and talks to an Ollama server directly
(streaming chat). The Flask backend only exposes /api/ollama/models so the UI
can populate its model dropdown. To keep the AI grounded in reality, it uses
Kroft's own endpoints as tools:
/api/msf/modules/suggestand/validateso it only ever proposes modules that actually exist in your Metasploit install,/api/msf/console_execto run command blocks (output is banner-stripped and smartly truncated to fit the model's context),/api/report/<ip>to assemble everything known about a host for a write-up.
The autopilot mode wraps this in a loop: choose one action, observe the result, choose the next.
The UI is plain server-rendered HTML plus vanilla JavaScript — no npm, bundler, or framework. Tailwind and xterm.js load from CDNs, so there is nothing to compile.
- HTML is composed with Jinja2 includes.
templates/index.htmlis just a shell: the<head>, the page skeleton, and a series of{% include 'partials/…' %}tags. Each tab, modal, the sidebar, and the header live in their own partial undertemplates/partials/. The Tailwind<style>block stays inline (in_styles.html) because the Tailwind Play CDN compiles it at runtime. - JavaScript is split by feature into ordered files under
static/js/(01-core.js…13-init.js), loaded with plain<script>tags at the end of the body. They are classic scripts, not ES modules, so they share one global scope — exactly like the original single inline script did. This is what keeps every inlineonclick="…"handler working untouched. - Load order is the contract. The files are loaded in the same order the code
was originally written, and
13-init.js(which kicks offfetchHosts()etc.) runs last, after every function is defined. When editing, keep load-time calls in the file that defines what they use (or in13-init.js).
The Cyberspace tab (static/js/14-cyberspace.js) is a three.js scene driven entirely by Kroft's real telemetry — it scripts nothing. It's cosmetic: a window onto the live tools, safe to ignore.
Two clocks keep it honest:
- A recorder that's always on. A lightweight poll (every ~2s) of
/api/hosts,/api/jobs,/api/msf/jobs,/api/msf/sessionsand/api/eventsruns from page load — even while the tab is hidden — and writes a timestamped timeline: when each host was discovered, its status transitions, session open/close times, and the discrete "something happened" pulses. The timeline is what makes playback possible. The data model is pure (no three.js), so recording never depends on the renderer. - A renderer that only runs when visible. The WebGL render loop is started on
tab-open and paused on tab-close (no wasted GPU). Each frame it reconstructs
the scene at the current playhead time
T— which hosts exist, their status colors, which are owned — so the exact same code path serves both live mode (T = now) and replay (T = wherever you dragged the scrubber).
Visual language: hosts are wireframe nodes around the glowing Kroft core; status drives color (blue discovered → amber scanning → red under-attack → green owned); a green AI drone flies to the active target and fires scan/exploit beams at its ports; owned hosts sprout an inner bot and beam pivot traffic to the next victim; and every interesting server action sends a bright packet that slingshots along a slow, decaying gravitational orbit before being swallowed by its destination (CVE lookups arc out to a distant internet node and back). Data that lands in the core (loot, recon, CVE intel) crystallizes into a colored shard that stays inside the core, so it visibly fills up as the engagement progresses. A packet-colour key sits in the HUD, and clicking any host opens a floating 3D dossier that types out its nmap details (click it again to dismiss).
The packet pulses come from the event feed (kroft/events.py):
an after_request hook (kroft/activity.py) maps the handful
of routes that represent real DB/MSF activity (loot stored, module looked up, CVE
queried, exploit dispatched, …) onto a bounded in-memory ring buffer, which the
visualizer polls via /api/events. Routine UI polling is deliberately not
recorded, so the traffic stays meaningful.
POST /api/msf/exploit {target_ip, module, options}
→ routes/msf/exploit.py: validate input + scope check (scope.in_scope)
→ create exploit_jobs[job_id]; spawn thread → services/msf_workers.run_exploit
→ return {job_id} (immediately)
...meanwhile, the worker thread:
→ validate module, set options, pick payload/LHOST, execute via MSF RPC
→ poll for a new session; update exploit_jobs[job_id] + ExploitLog row
UI polls GET /api/msf/jobs and GET /api/msf/jobs/<job_id>/output for status.
This brings up both the Kroft web app and a Metasploit RPC daemon, wired together on a private Docker network.
docker compose up --buildThen open http://localhost:5000.
What Compose starts:
-
msf-rpc— the officialmetasploitframework/metasploit-frameworkimage runningmsfrpcd(passwordmsfrpc, port55553). Its data is persisted to./msf_data. -
openvas— the single-containerimmauss/openvasimage, which bundles the whole Greenbone/GVM stack (gvmd, ospd-openvas, the scanner, postgres, redis, feeds) into one service and exposes GMP on9390and the Greenbone web UI (GSA) on9392. Kroft talks to it over GMP/TLS. Its feed DB is persisted to theopenvas_datavolume.⚠️ First boot is slow. OpenVAS downloads its vulnerability feeds on the initial run — this can take 15–30+ minutes and a few GB of disk. Until the sync finishes the Vuln Scanner tab shows the scanner offline and scans return a "not reachable yet" error; the rest of Kroft works normally. Theopenvas_datavolume means this only happens once. -
kroft-scanner— this app, built from theDockerfile(which installs nmap and the Python deps). It is configured via environment variables to reach the RPC + OpenVAS containers and runs privileged so nmap can perform OS detection / raw socket scans.
Prerequisites: Python 3.10+, the nmap binary, and a running msfrpcd if you
want the Metasploit features.
# 1. System dependency
sudo apt-get install -y nmap # (or your platform's package manager)
# 2. Python dependencies
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# 3. (Optional) start the Metasploit RPC daemon
msfrpcd -P msfrpc -S -a 127.0.0.1 -p 55553 -f
# 4. Run Kroft
python app.pyOpen http://localhost:5000. The app starts fine without Metasploit or OpenVAS —
those features simply report "not connected" / "offline" until the respective
service is reachable. (OpenVAS is heavy to run standalone; Docker Compose is the
recommended way to bring it up. Point GVM_HOST/GVM_PORT at any GMP endpoint.)
Note: OS detection and some scan types require root/raw-socket privileges. Run with appropriate privileges (or via the privileged Docker container).
Dev vs. debug:
python app.pyruns with debug off by default (production-safe). For the auto-reloader and interactive debugger while developing, setKROFT_DEBUG=1— but never in production (Werkzeug's debugger is a remote-code-execution console).
Two constraints drive how Kroft must be deployed:
- Single process, always. Live state (scan jobs, exploit jobs, sessions,
consoles) lives in in-memory registries (
kroft/state.py). Threads are fine, but multiple worker processes are not — each would get its own copy and the UI would see jobs/sessions blink in and out. Run exactly one worker. - Debug off. Ensure
KROFT_DEBUGis unset or0.
app is the WSGI callable, so put a single-worker production server in front of
the Flask dev server:
# gunicorn: one worker, many threads (threads carry the concurrency)
gunicorn --workers 1 --threads 8 --timeout 120 app:app
# …or waitress (no system deps)
waitress-serve --threads=8 --listen=0.0.0.0:5000 app:appBecause this is effectively a remote-controlled exploitation platform, also put it behind authentication / a VPN and bind it to a trusted interface — see Security notes.
All configuration is via environment variables (see kroft/config.py); every one
has a working default.
| Variable | Default | Purpose |
|---|---|---|
MSF_HOST |
127.0.0.1 |
Host of the Metasploit RPC daemon. |
MSF_PORT |
55553 |
Port of msfrpcd. |
MSF_PASSWORD |
msfrpc |
RPC password. |
GVM_HOST |
127.0.0.1 |
Host of the OpenVAS/Greenbone GMP endpoint (openvas under Compose). |
GVM_PORT |
9390 |
GMP (TLS) port. |
GVM_USERNAME |
admin |
GMP username Kroft authenticates as. |
GVM_PASSWORD |
admin |
GMP password (keep in sync with the openvas container's PASSWORD). |
GVM_SCAN_CONFIG_ID |
daba56c8-… |
Scan config UUID (default: Full and fast). |
GVM_SCANNER_ID |
08b69003-… |
Scanner UUID (default: OpenVAS default scanner). |
GVM_PORT_LIST_ID |
33d0cd82-… |
Port-list UUID (default: All IANA assigned TCP). |
OLLAMA_BASE |
https://ollama.local.craysoftware.com |
Ollama server used by Kroft.AI (the browser must be able to reach this). |
KROFT_DB |
sqlite:///kroft_assets.db |
SQLAlchemy database URL. |
KROFT_HOST |
0.0.0.0 |
Bind address (used by kroft/config.py; app.py runs on 0.0.0.0:5000). |
KROFT_PORT |
5000 |
Port. |
KROFT_DEBUG |
1 |
Flask debug flag. |
The engagement scope (scope_cidr) is not an environment variable — it is set
at runtime in the Settings UI (or via POST /api/settings) and stored in the
database. An empty scope allows all targets; otherwise intrusive actions are
restricted to the listed CIDR(s).
All responses are JSON unless noted.
| Method | Path | Description |
|---|---|---|
GET |
/ |
The single-page UI. |
POST |
/api/scan |
Start an nmap scan. Body: {target, custom_args} → {job_id}. |
GET |
/api/jobs |
List nmap scan jobs (most recent first). |
GET |
/api/hosts |
List all discovered hosts. |
DELETE |
/api/hosts/<id> |
Delete a host. |
POST |
/api/hosts/<id>/tags |
Set a host's tags. Body: {tags}. |
GET |
/api/hosts/export?format=csv|json |
Export the inventory. |
| Method | Path | Description |
|---|---|---|
GET |
/api/loot[?host=<ip>] |
List loot (optionally filtered by host). |
POST |
/api/loot |
Add loot item(s) (deduped). Body: a loot object or {items:[…]}. |
DELETE |
/api/loot/<id> |
Delete a loot item. |
GET |
/api/report/<ip> |
Aggregate host + exploit logs + loot + OpenVAS vulns for a report. |
GET |
/api/cve?q=<product+version> |
NVD CVE lookup (best-effort, cached). |
GET/POST |
/api/settings |
Read / write the key-value settings (e.g. scope_cidr). |
| Method | Path | Description |
|---|---|---|
GET |
/api/openvas/status |
Scanner connection status + GMP version (cached, non-blocking). |
GET |
/api/openvas/configs |
Available scan configs for the dropdown (falls back to the default). |
POST |
/api/openvas/scan |
Start a vuln scan. Body: {target, config_id?} → {job_id}. (scope-checked) |
GET |
/api/openvas/jobs |
List vuln-scan jobs with live phase/progress. |
GET |
/api/openvas/jobs/<job_id> |
One job's detail. |
GET |
/api/openvas/jobs/<job_id>/output |
The scan's summary text (for the AI feed / job detail). |
GET |
/api/openvas/vulns[?host=<ip>] |
List findings (most severe first), optionally by host. |
DELETE |
/api/openvas/vulns/<id> |
Delete a finding. |
GET |
/api/openvas/export?format=csv|json[&host=<ip>] |
Export findings. |
| Method | Path | Description |
|---|---|---|
GET |
/api/msf/status |
RPC connection status + version. |
POST |
/api/msf/scan |
Run db_nmap inside Metasploit. Body: {target}. (scope-checked) |
GET |
/api/msf/modules/search?q=&type= |
Search modules. |
POST |
/api/msf/modules/suggest |
Verified module suggestions from recon keywords. Body: {keywords, type}. |
GET |
/api/msf/modules/validate?module=&type= |
Check a module loads; suggest alternatives if not. |
GET |
/api/msf/modules/info?module=&type= |
Module options, payloads, references. |
POST |
/api/msf/exploit |
Dispatch an exploit (or aux/post). Body: {target_ip, module, options} → {job_id}. (scope-checked) |
POST |
/api/msf/post |
Dispatch a post/auxiliary module. Body: {module, options, type} → {job_id}. |
GET |
/api/msf/jobs |
List MSF exploit/aux/post jobs. |
GET |
/api/msf/jobs/<job_id>/output |
Full captured output for a job. |
POST |
/api/msf/jobs/<job_id>/kill |
Kill one MSF framework job. |
POST |
/api/msf/jobs/kill_all |
Kill all MSF framework jobs. |
GET |
/api/msf/exploit_logs |
Recent exploit log entries (audit trail). |
GET |
/api/msf/sessions |
List live sessions (synced from MSF). |
POST |
/api/msf/sessions/<sid>/exec |
Run a command in a session. Body: {cmd}. |
GET |
/api/msf/sessions/<sid>/read |
Poll a session for unsolicited output. |
POST |
/api/msf/sessions/<sid>/kill |
Terminate a session. |
POST |
/api/msf/console_exec |
Run a batch of console commands; returns trimmed output. Body: {commands:[…]}. |
POST |
/api/msf/console/create |
Create a persistent interactive console. |
POST |
/api/msf/console/<cid>/write |
Send input to a console. Body: {input}. |
GET |
/api/msf/console/<cid>/read |
Read pending console output. |
POST |
/api/msf/console/<cid>/destroy |
Destroy a console. |
| Method | Path | Description |
|---|---|---|
GET |
/api/ollama/models |
List models available on the configured Ollama server. |
GET |
/api/events?since=<seq> |
Activity event feed for the Cyberspace visualizer. Returns {events, last_seq}; poll with the last seq for incremental updates. |
- Authorization first. Only use Kroft against systems you own or are authorized to test.
- Scope guardrail. Set
scope_cidrin Settings to restrict intrusive endpoints (/api/msf/scan,/api/msf/exploit) to your authorized range. It guards single hosts; ranges/hostnames are passed through, so define scope carefully. - No authentication. The web UI has no built-in auth and binds to
0.0.0.0. Run it only on a trusted, isolated network (or behind your own auth/VPN). Do not expose it to the internet. - Debug mode. The development server runs with
debug=True. For a real deployment, front it with a production WSGI server and disable debug. - Privileged operations. nmap OS detection and Metasploit need elevated
privileges; the Docker setup runs the scanner container as
privileged.
- Application factory.
kroft/create_app()builds the app: it runsinit_db(), starts the background MSF connection manager, and registers all blueprints. Import it anywhere (e.g. tests) without side effects beyond those. - Adding an endpoint. Put the handler in the relevant
kroft/routes/*blueprint (or a new one registered inroutes/__init__.py), and keep any real logic inkroft/services/. - Shared state. Mutate the registries in
kroft/state.pyonly while holding the matching lock (jobs_lock,msf_lock,console_lock). - Background work. Anything that can take more than a moment should run in a daemon thread and report progress through a state registry, as the existing scan/exploit workers do.
- Runtime: Flask, SQLAlchemy, python-nmap, pymetasploit3, requests
(see
requirements.txt/Pipfile). - External: the
nmapbinary, a Metasploit RPC daemon (msfrpcd), and an Ollama server for the AI features.