ηΉι«δΈζ | English
Next-Generation Mythic C2 Interface
Cyberpunk-styled, real-time, collaborative Command & Control UI built for advanced red-team operators
- Overview
- Screenshots
- Feature Matrix
- Application Map
- Tech Stack
- Quick Start (Production)
- Development Mode (Hot Reload)
- Metasploit Integration
- Setup Script (
minerva_install.sh) - Mythic Source Patches (
mythic_change.sh) - Project Structure
- Architecture
- Routing & Sidebar
- Nginx Proxy Layout
- Theme System
- Battle Mode
- Audio System
- Custom Graph Nodes
- Authentication & Sessions
- Environment Variables
- Troubleshooting
- License
Minerva is a modern, cyberpunk-themed web interface for the Mythic C2 Framework. It is a drop-in replacement for Mythic's built-in MythicReactUI, designed from the ground up for operators who run long red-team engagements and need a dense, low-friction operational console.
Compared to the stock Mythic UI, Minerva adds:
- Real-time collaborative graphs β ReactFlow-powered callback topology with shared custom nodes for relay / proxy infrastructure, synced every 5 s across all logged-in operators via Hasura.
- 3D cyber-topology β Three.js scene with orbit controls, subnet (CIDR) grouping, physics-based positioning, dashed P2P links, and context menus.
- Rich interactive console β Multi-tab terminal with structured output blocks, Mimikatz parsing, process list rendering, file-browser overlays, and inline tasking forms.
- Quick Hack workflows β Pre-canned, one-click red-team workflows over callbacks (recon, persistence, dumping, lateral movement) chained as tasking macros.
- Native Metasploit integration β First-class MSF-RPC client with launch dashboard, session-lifecycle management, persistent execution history, and live task-browser output parsing.
- MITRE ATT&CK matrix β Full T-id matrix with task / command / tag overlays so operators can see live coverage of techniques.
- Eventing workflows β Visual builder for Mythic eventing instances with keyword triggers and conditional steps.
- Battle Mode β Tactical UI mode (Combat / Recon / Normal) that re-tunes density, animation speed, and ambient sound for active operations.
- Theming & audio β CSS-variable driven dark/light themes, custom background image, JetBrains Mono / Inter typography, IndexedDB-backed music library, and per-event SFX.
Minerva can run two ways:
- Standalone Docker β
docker compose up -dbrings up two containers:minerva-dev(the React app served byreact-app-rewired, the same way Mythic serves its own UI) behind aminervaNginx container that terminates TLS on 443 and proxies/graphql,/auth,/refresh,/msf-rpc,/directto an existing Mythic instance. Self-signs a TLS cert on first run. - Replace
mythic_reactβ Usescripts/minerva_install.shto swap Minerva into Mythic's ownMythicReactUIdirectory so it ships through Mythic's normal lifecycle (./mythic-cli ...).
Cyberpunk-styled authentication with real-time server status monitoring, HTTPS encryption indicator, and a session-state tracker.
Central operational overview β active callbacks, total payloads, C2 infrastructure status, operation details, command statistics, asset-collection metrics, top commands and a recent activity feed.
Live event stream with alert counter. Drives the sidebar notification bell and surfaces new callbacks, alerts, custom events, feedback and startup events as they happen.
Operation lifecycle management with status tracking (Active / Complete / Deleted), operator assignments, and per-operation OPSEC command blocklists.
Per-operation OPSEC controls β command blocklists, role-based gates, and tasking-time enforcement.
ReactFlow graph view showing the Minerva core node connected to active agents. Shared custom nodes model relay / proxy infrastructure. The sortable data table below supports bulk actions, sleep / jitter editing, grouping, and last-checkin badges.
Tab picker for the multi-callback interactive console. Displays every previously opened tab so operators can jump between callbacks without losing context.
Rich command tasking with structured output blocks β Mimikatz parsing, process listings, file-browser overlays, inline tasking forms, drag-and-drop uploads, and a real-time streaming task block.
Per-task deep-view with full host tree, parameter inspector, structured output viewer, and prev/next task navigation.
Hub for payload listing, multi-step Create-Payload wizard, and the Wrapper flow. Supports import / export of payload configurations and rebuild-from-existing.
Step-by-step build pipeline: OS β type β commands β C2 β build. Each step persists state so operators can step back and adjust without losing progress.
Unified view of every installed agent / wrapper / translator / consuming-service / custom-browser. Header toolbar adds search, sort (name / status / commands), online-only filter, and a show-deleted toggle. Each card shows the agent's SVG icon, container status, build-parameter inspector, command browser, container-file editor, and one-click test of webhook / logger events.
Centralized file management with a categorized sidebar for Downloads, Uploads, Screenshots, and Eventing workflow files. Includes the target-machine file-browser tree.
Credential storage with multi-field search (Account, Realm, Credential, Comment, Tag). Tracks verified vs harvested counts and links each credential back to its originating task.
Indicator-of-compromise / artifact viewer with task linkage and host attribution.
Global cross-entity search across tasks, files, credentials, callbacks, and artifacts with advanced filtering.
C2 communication profile management showing all installed profiles (discord, dns, github, http, https, tcp, websocket) with version info, status indicators, container-file listing / editing, and start/stop controls.
Tunnel management with a visual flow diagram showing operator-side proxy, C2 server relay, and target-side endpoint. Displays active tunnel status, port mappings, and the full connection chain.
Full Three.js 3D map with interactive orbit controls. Nodes are color-coded by type (Core / Alive / Dead / Custom). Dashed lines indicate P2P relations; a tunnel layer overlays active SOCKS / RPORTFWD chains; a legend / status bar tracks real-time node counts.
One-click red-team workflow library (recon / persistence / dumping / lateral) that chains commands across selected callbacks. Workflows are JSON-defined and operator-extensible.
Native MSF-RPC client. Tabs cover Dashboard (sessions / jobs / modules), Launch Attack (module browser + parameter form), Operations (live sessions, jobs, routes), and Task History (persistent execution history with full output).
Visual workflow builder for Mythic eventing β event groups, instances, keyword triggers, conditional steps, and a real-time stream of matching events.
Full MITRE ATT&CK matrix visualization with 637 techniques mapped across all tactical categories. Filter by Tasks, Tasks/PT, Commands, or Tags β cells light up to show live execution coverage.
Operator administration: create, edit, deactivate, change passwords, and toggle admin roles.
Report builder driven by operation data with analytics, filters, and export options.
Editable browser-script library with virtualized tables, sortable columns, tabs rendering, and per-payload-type scoping.
Tag-based organization and filtering across all entities.
Comprehensive preferences panel covering operator preferences, display toggles, timestamp formatting, task-interaction modes, browser-script options, audio / music library, theme palette, and sidebar shortcut ordering.
| Feature | Description |
|---|---|
| Callbacks | Real-time callback tracking with health indicators (alive/dead/streaming), bulk operations, grouping, last-checkin badges, and sleep/jitter editing |
| Console | Multi-tab interactive command tasking with syntax-highlighted output blocks, split-view DB output, command history, autoScroll toggle, drag-and-drop file uploads, and streaming task results |
| Tasks | Dedicated single-task view with full host tree, parameter inspector, output viewer, and per-task navigation |
| Payloads | Multi-step Create-Payload wizard (OS β type β commands β C2 β build), Wrapper flow, payload import/export, rebuild-from-existing, and tab-cap on browser-script tabs output |
| Files | Download / upload tracking, screenshot viewer with thumbnail grid, keylog search, drag-and-drop modal uploads, and artifact organization |
| Credentials | Vault with deduplication, hash management, account linking, and multi-field search |
| Search | Global cross-entity search across tasks, files, credentials, callbacks, and artifacts with advanced filtering |
| Artifacts | Indicator-of-compromise / artifact viewer with task linkage |
| Tags | Tag-based organization and filtering across all entities |
| Feature | Description |
|---|---|
| Callback Graph | Interactive 2D graph using ReactFlow with ELK auto-layout, custom node creation, edge management, PNG export, and a graph-config panel |
| 3D Topology | Three.js 3D network map with orbit controls, subnet grouping (CIDR), physics-based positioning, tunnel-layer overlay, and right-click context menus |
| Custom Nodes | Operator-defined relay / proxy nodes stored server-side in Hasura agentstorage; synced across all connected operators every 5 s |
| MITRE ATT&CK | Full ATT&CK matrix with technique mapping, execution tracking, and Task / Command / Tag overlays |
| Tunnel Map | Cyberpunk flow diagram showing parent-child tunnel relationships, port mappings, and live status |
| Feature | Description |
|---|---|
| Battle Mode | Combat / Recon / Normal mode switching with tactical UI optimizations (2Γ animation speed in Combat, dimmed non-critical info in Recon) |
| Eventing | Visual workflow builder for Mythic eventing β event groups, instances, keyword triggers, conditional steps, real-time stream of matching events |
| Quick Hack | One-click red-team workflow library (recon / persistence / dumping / lateral) that chains commands across selected callbacks |
| Metasploit | Native MSF-RPC client with launch dashboard, session list, job control, stored credentials, and persistent execution history |
| Operations | Operation lifecycle management with role-based access and per-op OPSEC command blocklists |
| Reporting | Report generation from operation data with analytics |
| C2 Profiles | Profile configuration, container file listing / editing, and start/stop control |
| PayloadTypes | Unified view of every installed agent / wrapper / translator / consuming-service / custom-browser with live status, build-parameter inspector, command browser, container-file editor, and one-click test of webhook / logger events |
| Browser Scripts | Editable custom browser-script library with virtualized tables, sortable columns, tabs rendering, and per-PT scoping |
| Audio System | Global music player (IndexedDB-stored library), per-event sound effects (callback, tunnel, auth, error), individual SFX toggles |
| Theme & Palette | Dark / Light themes, customizable accent colors, custom background image, JetBrains Mono / Inter typography |
The whole UI is mounted under /new/... (so it can co-exist with stock mythic_react). Routes:
| Path | Page | Purpose |
|---|---|---|
/new/login |
Login |
JWT auth + server status / SSL indicator |
/new/invite |
Invite |
Operator invite-link registration |
/new/dashboard |
Dashboard |
Operational overview & activity feed |
/new/events |
EventFeed |
Live event stream w/ alert counter |
/new/callbacks |
Callbacks |
Active callback table + graph view |
/new/callbacks/:displayId |
Callbacks |
Focused callback (deep-link) |
/new/console |
ConsoleSelection |
Console tab picker |
/new/console/:id |
Console |
Interactive tasking terminal |
/new/task Β· /new/task/:displayId |
SingleTaskView |
Per-task deep view |
/new/payloads |
Payloads |
Payload list + tabs (list / create / wrapper) |
/new/create-payload/* |
CreatePayload |
Multi-step build wizard |
/new/create-wrapper |
(redirect) | β /payloads?tab=wrapper |
/new/credentials |
Credentials |
Credential vault |
/new/files |
Files |
File manager + screenshots |
/new/c2-profiles |
C2Profiles |
C2 profile management |
/new/payload-types |
PayloadTypes |
All installed agents / services |
/new/tunnels |
Tunnels |
SOCKS / RPORTFWD topology |
/new/topology |
Topology3D |
3D network map |
/new/quickhacks |
QuickHacks |
One-click workflow library |
/new/metasploit |
Metasploit |
MSF-RPC dashboard / attack / history |
/new/eventing |
Eventing |
Workflow / event-group builder |
/new/mitre |
MitreAttack |
ATT&CK matrix |
/new/search |
Search |
Global search |
/new/artifacts |
Artifacts |
Artifact viewer |
/new/reporting |
Reporting |
Report builder |
/new/operations |
Operations |
Operation lifecycle + OPSEC blocklists |
/new/users |
Users |
Operator administration |
/new/browser-scripts |
BrowserScripts |
Custom browser scripts |
/new/tags |
Tags |
Tag management |
/new/opsec |
Opsec |
Operation OPSEC controls |
/new/settings |
Settings |
All operator preferences |
Sidebar items can be re-ordered or hidden per-operator via Settings β Sidebar Shortcuts. The default list is also where
/new/jupyterand/new/graphqlexternal links live (they open Mythic's Jupyter and Hasura console respectively).
| Category | Technologies |
|---|---|
| Frontend | React 19, TypeScript 5.9+, React Router 7 |
| Styling | Tailwind CSS 3.4, Material-UI 7, Emotion, Framer Motion |
| State | Zustand 5 (persisted app store), Apollo Client 4 (GraphQL + cache + reactive vars) |
| Real-time | GraphQL subscriptions over WebSocket via graphql-ws |
| 3D | Three.js 0.183, @react-three/fiber, @react-three/drei |
| Graph | @xyflow/react 12.6 + elkjs 0.11 hierarchical layout |
| Charts | MUI X Charts, MUI X Data Grid |
| Editor | React Ace (syntax highlighting in code editors / Eventing workflows) |
| Data & Storage | IndexedDB (musicDB, custom-graph-node cache), sql.js for local SQLite, Hasura agentstorage for shared state |
| Animation | Framer Motion (transitions, modals), CSS animations (scan-lines, glitch) |
| Build | React App Rewired 2.2, Webpack 5, PostCSS, config-overrides.js |
| Deploy | Docker, Nginx (SSL + reverse proxy + WS upgrade) |
| External | MSF-RPC (Metasploit Framework) via JSON-RPC over HTTP |
- Docker and Docker Compose
- A running Mythic C2 instance reachable from the host (default:
https://host.docker.internal:7443) - Open port 443 on the host
git clone https://github.com/redmeow-tw/Minerva.git
cd Minerva
# Build the app + Nginx images, then run (self-signed cert auto-generated)
docker compose build
docker compose up -dFirst start compiles the React app inside
minerva-devβ give it ~1β2 minutes, thenhttps://<host>/serves. TheminervaNginx container proxies to it once it's up.
Open https://<your-host>/ β you'll be redirected to /new/login. Log in with your Mythic credentials.
To point at a remote Mythic instance:
MYTHIC_ADDRESS=https://10.0.0.5:7443 docker compose up -dTo stop:
docker compose downThe default
docker-compose.ymlexposes only Minerva (port 443).MYTHIC_ADDRESSis passed into Nginx as a template variable and used for/graphql,/auth,/refresh,/invite,/directupstreams. Drop your ownminerva.crt/minerva.keyintonginx/ssl/to replace the auto-generated self-signed cert.
If you want Minerva to be Mythic's web UI (handled by ./mythic-cli), use the bundled setup script:
# From /opt/Minerva
./scripts/minerva_install.sh # full install (backup + copy + build + apply patches)
./scripts/minerva_install.sh verify # verify install
./scripts/minerva_install.sh status # show container status & logs
./scripts/minerva_install.sh fix # re-sync src and rebuild
./scripts/minerva_install.sh clean # clean custom graph nodes from DB
./scripts/minerva_install.sh uninstall # restore original MythicReactUI from backup
# Metasploit:
./scripts/minerva_install.sh msf-start # start MSF-RPC container
./scripts/minerva_install.sh msf-stop # stop MSF-RPC container
./scripts/minerva_install.sh msf-status # status + logs
./scripts/minerva_install.sh msf-verify # Python connectivity checkThe script:
- Backs up the original
MythicReactUItoMythicReactUI.bak. - Copies Minerva's
src/, config files,Dockerfile, andpackage*.jsonintoMythicReactUI. - Runs
mythic_change.shto patch Mythic's Go source (see below). - Configures the Hasura
agentstoragetable so custom graph nodes can sync between operators. - Rebuilds the
mythic_reactcontainer.
Set MYTHIC_DIR env var if your Mythic install is not at /opt/Mythic.
Dev mode uses two containers:
| Container | Role | Description |
|---|---|---|
minerva-dev |
React Dev Server | Runs react-app-rewired start on port 3000 with HMR. Source code is mounted as volumes so any change triggers an instant browser refresh. |
minerva |
Nginx SSL Proxy | Listens on 443 with self-signed SSL. Proxies /new/ β dev server, /ws β HMR WebSocket, and /graphql/, /auth, /refresh, /invite, /msf-rpc/, /direct/ β Mythic. |
Browser :443 ββ nginx (SSL) ββ minerva-dev :3000 (React dev server + HMR)
βββ Mythic :7443 (API / GraphQL / WebSocket)
βββ Metasploit :55553 (optional MSF-RPC)
docker compose -f docker-compose.dev.yml up -d --build
docker logs -f minerva-dev # wait for "webpack compiled"Open https://<your-host>/ β any change under src/ or public/ hot-reloads in < 1 s.
| Host Path | Container Path | Purpose |
|---|---|---|
./src/ |
/app/src/ |
React source (hot reload) |
./public/ |
/app/public/ |
Static assets |
./tailwind.config.js |
/app/tailwind.config.js |
Tailwind theme |
./postcss.config.js |
/app/postcss.config.js |
PostCSS |
./config-overrides.js |
/app/config-overrides.js |
Webpack overrides |
./tsconfig.json |
/app/tsconfig.json |
TypeScript config |
./.env |
/app/.env |
Build-time env vars |
node_modules/andpackage.jsonare not mounted β they live in the image. After adding / removing npm packages, rebuild withdocker compose -f docker-compose.dev.yml up -d --build.
MYTHIC_ADDRESS=https://10.0.0.5:7443 \
docker compose -f docker-compose.dev.yml up -d --build# Dev (HMR) β Production (static build)
docker compose -f docker-compose.dev.yml down
docker compose up -d --build
# Production β Dev
docker compose down
docker compose -f docker-compose.dev.yml up -d --buildMinerva ships a first-class Metasploit page powered by an MSF-RPC daemon container.
React (Metasploit page)
βββ /msf-rpc/ (nginx, proxy_pass)
βββ minerva_msf :55553 (msfrpcd --user msf --pass minerva_msf -S -a 0.0.0.0)
# Option A: via minerva_install.sh wrapper
./scripts/minerva_install.sh msf-start
./scripts/minerva_install.sh msf-verify # Python sanity check via msfrpc_verify.py
# Option B: directly with compose
docker compose -f docker-compose.metasploit.yml up -dOverride credentials / port:
MSFRPC_USER=msf MSFRPC_PASS=changeme MSFRPC_PORT=55553 \
docker compose -f docker-compose.metasploit.yml up -d| Tab | Purpose |
|---|---|
| Dashboard | Connection state, host stats, session counts, recent jobs |
| Attack | Module browser, parameter form, launch with target / payload, save credentials, dry-run preview |
| Operations | Active sessions, jobs & routes β kill session, stop job, hop / portfwd |
| History | Persistent (IndexedDB) execution history of every launched attack with full output |
The MSF-RPC client lives in src/Minerva/pages/Metasploit/msfrpc.ts. The page polls getFullStatus every 15 s and lazy-loads each tab.
Unified entry point for installing Minerva into Mythic, managing the optional MSF-RPC service, and resetting state.
Usage: ./scripts/minerva_install.sh [command]
Commands:
(none) Full install (backup + copy + build + patches)
verify Verify installation is correct
fix Re-sync source and rebuild mythic_react
status Show container status and logs
clean Remove custom graph nodes from the database
uninstall Restore original MythicReactUI from backup
Metasploit:
msf-start Deploy & start Metasploit RPC container
msf-stop Stop Metasploit RPC container
msf-status Show Metasploit container status & logs
msf-verify Verify MSF-RPC connectivity (Python)
help Show this message
Environment:
MYTHIC_DIR Path to Mythic (default: /opt/Mythic)
The script is idempotent β re-running install is safe and will skip steps that are already complete.
A few Minerva features (array-type build parameters, payload re-import) need patched logic inside Mythic itself. scripts/mythic_change.sh applies these patches deterministically:
| File patched | Symptom without patch | Fix |
|---|---|---|
mythic-docker/src/rabbitmq/utils.go Β· GetFinalStringForDatabaseInstanceValueFromUserSuppliedValue β ARRAY case |
bad type for *_PARAMETER_TYPE_ARRAY: string when re-importing or rebuilding payloads whose array parameters arrive JSON-encoded as strings |
Add case string: that validates the input is a valid JSON array and returns it |
mythic-docker/src/rabbitmq/utils.go Β· getSyncToDatabaseValueForDefaultValue β ARRAY case |
Same error on agent sync when a C2 profile / payload type sends a JSON-encoded array default | Same case string: handler |
The script is invoked automatically by minerva_install.sh, but you can run it standalone:
MYTHIC_DIR=/opt/Mythic ./scripts/mythic_change.shRunning it twice is safe (idempotent).
Minerva/
βββ docker-compose.yml # Production (single nginx container)
βββ docker-compose.dev.yml # Development (nginx + dev server)
βββ docker-compose.metasploit.yml # Optional MSF-RPC daemon
βββ docker/
β βββ Dockerfile.prod # Build static React + Nginx
β βββ Dockerfile.dev # Node dev server + HMR
β βββ Dockerfile.nginx # Nginx (used in dev compose)
β βββ Dockerfile # Inside-Mythic build (mythic_react)
βββ nginx/
β βββ nginx.conf.template # Prod template (alias /new + proxies)
β βββ nginx.dev.conf.template # Dev template (proxy to dev server + /ws)
β βββ docker-entrypoint.sh # SSL cert generation + envsubst
βββ scripts/
β βββ minerva_install.sh # install / verify / fix / status / msf-*
β βββ mythic_change.sh # Patches Mythic Go source (array params)
β βββ configure-hasura-agentstorage.sh # Enable agentstorage for graph sync
β βββ clear-custom-nodes.sh # Wipe custom graph nodes from DB
β βββ clear-nodes.sql # SQL used by clear-custom-nodes
β βββ debug-custom-nodes.sh # Print custom-node state from Hasura
β βββ msfrpc_verify.py # Sanity check MSF-RPC connectivity
β βββ take_screenshots.js # README screenshot capture (Puppeteer)
β βββ take_login_only.js # One-shot login screenshot
βββ docs/ # Banner + screenshots
βββ public/ # Static assets (favicon, audio, etc.)
βββ tailwind.config.js # Theme tokens (signal/void/ghost/machine + accent)
βββ postcss.config.js
βββ config-overrides.js # Webpack overrides
βββ tsconfig.json
βββ package.json
βββ src/
βββ index.js # React root + Apollo + WS link
βββ cache.js # Apollo cache + reactive vars
βββ themes/ # MUI theme bridges
βββ components/ # Legacy shared components
βββ Minerva/
βββ App.tsx # Router + auth bootstrap (code-split routes)
βββ store.ts # Zustand app store (sidebar, audio, console tabs)
βββ index.css # Tailwind base + CSS vars + cyber-scrollbar
β
βββ context/
β βββ BattleModeContext.tsx
β βββ ThemeContext.tsx
β
βββ pages/ # All routes (lazy-loaded)
β βββ Dashboard.tsx
β βββ Login.tsx Β· Invite.tsx
β βββ Callbacks/ (graph + table + dialogs + utils)
β βββ Console/ (terminal + context menu + parsers)
β βββ ConsoleSelection.tsx
β βββ SingleTaskView/ (host tree, task detail, list)
β βββ Payloads/
β βββ CreatePayload/ (multi-step wizard)
β βββ CreateWrapper/
β βββ PayloadTypes/ (search/sort/agent icons + build params + commands + files)
β β βββ index.tsx
β β βββ BuildParamsDialog.tsx
β β βββ CommandsDialog.tsx
β β βββ ContainerFilesDialog.tsx
β βββ Files/ (filetable, screenshots, modals)
β βββ Credentials.tsx
β βββ C2Profiles.tsx
β βββ Tunnels/ Β· TunnelMap.tsx
β βββ Topology3D/ (3D scene + tunnel layer + detail panel)
β βββ QuickHacks.tsx
β βββ Metasploit/ (msfrpc, LaunchAttack, Operations, TaskBrowser, history)
β βββ Eventing/ (workflow builder, triggers, instances)
β βββ EventFeed.tsx
β βββ Operations/ (lifecycle + OPSEC blocklists)
β βββ Opsec.tsx
β βββ MitreAttack.tsx
β βββ BrowserScripts.tsx
β βββ Search/
β βββ Artifacts.tsx
β βββ Reporting.tsx
β βββ Tags.tsx
β βββ Users.tsx
β βββ Settings/ (Audio, Palette, SidebarShortcuts, rows)
β
βββ components/ # Reusable UI
β βββ Layout.tsx # Shared shell (sidebar + outlet)
β βββ Sidebar.tsx
β βββ CallbackGraph/ # ReactFlow graph + nodes + edges + layout
β βββ FileBrowser/ # Callback / server / virtual file trees
β βββ OutputRenderer/ # core, panels, parsed, graph renderers
β βββ CyberModal.tsx Β· CyberAlert Β· CyberDropdown Β· CyberTable
β βββ GlobalAudioPlayer.tsx
β βββ BattleMode.tsx
β βββ EventNotifications.tsx
β βββ ErrorBoundary.tsx
β βββ OSIcons.tsx
β βββ MythicConfirmDialog Β· MythicDialog Β· MythicFileUpload Β· MythicTextField β¦
β βββ β¦
β
βββ lib/
β βββ api/ # GraphQL queries / mutations / subscriptions, split per domain
β β βββ index.ts (re-exports everything)
β β βββ payloadTypes.ts (the file backing /payload-types)
β β βββ callbacks.ts Β· tasks.ts Β· files.ts Β· tunnels.ts Β· operations.ts β¦
β βββ auth.ts # JWT helpers, refresh logic
β βββ state.ts # Apollo reactive vars (meState, mePreferences)
β βββ snackbar.ts # toast helpers
β βββ soundEffects.ts # per-event SFX
β βββ musicDB.ts # IndexedDB music library
β βββ customGraphNodeService.ts # Shared graph nodes (Hasura agentstorage)
β βββ useQueryCompat.ts # Apollo 4 compat layer
β βββ utils.ts
β
βββ hooks/ # useCopyToClipboard, useDebounce, useFromNow, usePagination
βββ types/ # TS interfaces for every domain
βββ constants/ # api endpoints, colors
- GraphQL is the single transport for everything except the Metasploit RPC. Queries and mutations live in
lib/api/*.ts, grouped by domain. - Subscriptions use
graphql-wsover the samewss://<host>/graphql/endpoint. Pages such as Callbacks, EventFeed, Payloads, PayloadTypes, Tunnels, and Console rely on subscriptions for live updates. - Reactive variables (
meState,mePreferences) expose authenticated user state and preference overrides to any component.
- Every route is
React.lazy-imported inApp.tsxso the initial bundle is small; visiting a route streams in its chunk. - A single shared
<Layout />is mounted for every authenticated route so the sidebar, audio player, event notifications, and battle-mode shell never re-mount during navigation.
- Zustand store (
store.ts, persisted to localStorage) holds: sidebar collapse, console tabs, alert count, audio (music library, volume, per-SFX toggles), and notification preferences. - Apollo cache holds GraphQL entities.
- IndexedDB stores binary music files and a local custom-graph-node cache.
Custom graph nodes are stored server-side in Hasura's agentstorage table so every operator sees the same topology. customGraphNodeService.ts handles serialization, 5 s polling sync, conflict-tolerant merging, and DEBUG_GRAPH logging. The configure-hasura-agentstorage.sh script wires up the necessary Hasura permissions on install.
The sidebar (see components/Sidebar.tsx) lists every page. Operators can re-order or hide entries via Settings β Sidebar Shortcuts.
Default key set (used by getMythicSetting('sideShortcuts')):
dashboard Β· events Β· callbacks Β· console Β· task Β· payloads Β· credentials Β· files
c2-profiles Β· tunnels Β· quickhacks Β· users Β· search Β· topology Β· metasploit Β· settings
opsec Β· operations Β· artifacts Β· mitre Β· reporting Β· tags Β· browser-scripts Β· eventing
payload-types Β· jupyter Β· graphql
jupyter and graphql are external links that open Mythic's Jupyter notebook and Hasura console.
Nginx (port 443, self-signed SSL) is the single entry point. It performs SSL termination and proxies to either Mythic or Metasploit.
| Location | Upstream | Notes |
|---|---|---|
/ |
redirect to /new/login |
|
/new/ |
static bundle (prod) or minerva-dev:3000 (dev) |
hot reload + WS upgrade in dev |
/ws |
minerva-dev:3000/ws (dev only) |
webpack HMR socket |
/graphql/ |
${MYTHIC_ADDRESS}/graphql/ |
HTTP + WS upgrade, 86400 s read timeout |
/auth |
${MYTHIC_ADDRESS}/auth |
JWT acquisition |
/invite |
${MYTHIC_ADDRESS}/invite |
Operator invite registration |
/refresh |
${MYTHIC_ADDRESS}/refresh |
JWT refresh |
/direct/ |
${MYTHIC_ADDRESS}/direct/ |
File download |
/msf-rpc/ |
minerva_msf:55553 |
MSF-RPC JSON-RPC (optional) |
Buffers and bodies are tuned for large JWTs (16k) and 50 MB uploads.
Minerva uses CSS custom properties so themes can be swapped without recompiling. The base palette is defined in index.css:
/* Dark theme (default) */
:root {
--color-signal: 255 255 255 /* text & highlights */
--color-accent: 34 197 94 /* green accent */
--color-void: 0 0 0 /* background */
--color-ghost: 153 153 153 /* borders & secondary */
--color-machine: 51 51 51 /* card backgrounds */
}
/* Light theme */
:root.minerva-light {
--color-signal: 30 30 40
--color-accent: 22 163 74
--color-void: 240 240 245
--color-ghost: 90 90 100
--color-machine: 225 225 230
}Fonts: JetBrains Mono (monospace) and Inter (sans-serif).
Operators can also set a custom background image and per-component output colors via Settings β Palette.
context/BattleModeContext.tsx exposes three operational modes:
- NORMAL β default; full chrome & animation budget.
- RECON β dim non-critical chrome, prioritize legibility.
- COMBAT β tactical UI: 2Γ animation speed, accent color shifts to alarm-red, ambient SFX volume bumped.
Toggle via the sidebar's combat / recon icons. The mode is persisted in the Zustand store.
Two-layer audio:
- Global music player β user-uploaded tracks stored in IndexedDB (
musicDB). Playback survives navigation and survives full page reloads viauseAppStorestate (musicPlaying,musicTrackId). - Sound effects β per-event SFX for new callbacks, tunnels, auth alerts, key clicks, etc. Individual SFX can be toggled via Settings β Audio.
All audio respects the global sfxEnabled / musicEnabled flags.
Custom nodes model relay / proxy infrastructure that Mythic doesn't natively know about. They are persisted in Hasura's agentstorage table so all operators see the same view.
| Action | How |
|---|---|
| Create node | Right-click empty space in Callbacks β Graph View β Create Custom Node |
| Connect nodes | Right-click a node β Set Parent |
| Edit / delete | Right-click a node β Edit / Delete |
| Reset all | ./scripts/clear-custom-nodes.sh |
Each node stores hostname, IP, OS, architecture, C2 profile selection, position, and color. Positions persist across sessions; data syncs across connected operators via 5 s polling. Toggle DEBUG_GRAPH = true in CallbackGraph/index.tsx for verbose logging.
- JWT-based authentication (access + refresh tokens) via
/auth,/refresh. - 4-hour JWT lifetime with automatic background refresh.
- WebSocket re-auth on token renewal so GraphQL subscriptions never break.
- Session-expiry detection β toast warning at 30 minutes remaining and forced logout on expiry.
- All routes inside
<Layout />require a validmeState; anonymous users are redirected to/login.
| Variable | Default | Purpose |
|---|---|---|
MYTHIC_ADDRESS |
https://host.docker.internal:7443 |
Nginx upstream for all Mythic API calls |
MSFRPC_USER |
msf |
Username for MSF-RPC (docker-compose.metasploit.yml) |
MSFRPC_PASS |
minerva_msf |
Password for MSF-RPC |
MSFRPC_PORT |
55553 |
Port exposed by minerva_msf |
MYTHIC_DIR |
/opt/Mythic |
Used by minerva_install.sh & mythic_change.sh |
CHOKIDAR_USEPOLLING |
true (dev) |
Forces file polling inside Docker for HMR |
WDS_SOCKET_PATH |
ws (dev) |
HMR socket path behind Nginx |
WDS_SOCKET_PORT |
443 (dev) |
HMR socket port behind Nginx |
| Issue | Solution |
|---|---|
| CSS not loading | Ensure tailwind.config.js and postcss.config.js are mounted (dev) or copied (prod). Rebuild with --build. |
| Hot reload not working | Check docker logs minerva-dev. Dev server uses CHOKIDAR_USEPOLLING=true for Docker. |
MODULE_NOT_FOUND after editing |
Check volume mounts in docker-compose.dev.yml. |
| New npm package not found | Rebuild: docker compose -f docker-compose.dev.yml up -d --build |
| Browser SSL warning | Expected β self-signed cert. Trust the cert or accept the warning. |
bad type for *_PARAMETER_TYPE_ARRAY: string on payload build/import |
Run ./scripts/mythic_change.sh then rebuild mythic_server. |
| Graph nodes not syncing | Run ./scripts/minerva_install.sh fix β verifies the Hasura agentstorage table. |
| Graph nodes corrupted | ./scripts/clear-custom-nodes.sh to wipe and start clean. |
| Metasploit page shows "offline" | ./scripts/minerva_install.sh msf-status and msf-verify. Check that MSFRPC_USER / PASS in Settings match what msfrpcd is running with. |
| Sidebar items missing | Settings β Sidebar Shortcuts β the saved order may have hidden new items. Reset to defaults. |
| JWT expired toast keeps appearing | The browser's clock may be skewed; sync system clock and clear localStorage. |
This project is dual-licensed:
-
Open Source β AGPL-3.0 You may use, modify, and distribute this software under AGPL-3.0. Any derivative work or service using this software must also be released under AGPL-3.0.
-
Commercial License β for proprietary / closed-source use without AGPL obligations. Contact: [email protected]




























