Passive ICS/SCADA network discovery and topology visualization for OT security assessments.
Kusanagi Kajiki is a ground-up rewrite of the NSA's GRASSMARLIN (archived 2023), rebuilt from scratch with a Rust backend (Tauri 2.0) and SvelteKit frontend. It passively discovers and maps Industrial Control System (ICS) and SCADA network devices by analyzing network traffic captures and integrating data from external security tools.
In operational technology environments, active scanning can crash PLCs and disrupt physical processes. Assessors need visibility into OT networks without generating a single packet. Kusanagi Kajiki operates in passive-only mode — it observes captured traffic, identifies devices and protocols, maps network topology, and flags security concerns, all without touching the production network.
The tool achieves full feature parity with GRASSMARLIN 3.2 and extends well beyond it with MITRE ATT&CK for ICS detection, Purdue Model enforcement, Zeek/Suricata log ingestion, professional PDF reporting, SBOM/STIX export, baseline drift detection, and a modern dark/light UI. The name is a bilingual nod to the original: 草 (kusa/grass) + marlin (kajiki/カジキ), with Kusanagi (草薙) referencing the legendary sword from Japanese mythology.
conn.log, modbus.log, dnp3.log, s7comm.log with automatic field mapping[active-scan] tagging to distinguish from passive observation.kkj archives — Portable ZIP-based session format for sharing assessment data--open <file> (PCAP or .kkj), --import-pcap <path> for headless workflowsKusanagi Kajiki implements every major GRASSMARLIN 3.2 feature and adds capabilities the original never had:
| Capability | GRASSMARLIN 3.2 | Kusanagi Kajiki |
|---|---|---|
| Signature format | XML (opaque) | YAML (human-readable, git-friendly) |
| Security analysis | None | ATT&CK for ICS + Purdue Model + anomaly scoring |
| External tool integration | None | Zeek, Suricata, Nmap, Masscan |
| Reporting | None | PDF assessment reports |
| Compliance export | None | SBOM (CISA BOD 23-01), STIX 2.1 |
| Baseline comparison | None | Session drift detection with quantified scoring |
| Deep protocol parsing | Limited | Modbus FC 43/14 Device ID extraction, DNP3 deep parse |
| Session format | XML archives | SQLite + portable .kkj ZIP archives |
| Theming | Java Swing | Modern dark/light with CSS custom properties |
| CLI support | None | --open, --import-pcap |
| Architecture | Monolithic Java | 9 Rust crates + SvelteKit frontend |
| Protocol | Port(s) | Detection | Standard / Vendor |
|---|---|---|---|
| Modbus TCP | 502 | Deep parse | Schneider Electric, multi-vendor |
| DNP3 | 20000 | Deep parse | IEEE 1815 (utilities, substations) |
| EtherNet/IP (CIP) | 44818, 2222 | Signature | Rockwell / Allen-Bradley |
| BACnet/IP | 47808 | Signature | ASHRAE (building automation) |
| S7comm | 102 | Signature | Siemens S7 PLCs |
| OPC UA | 4840 | Port + Signature | OPC Foundation |
| IEC 60870-5-104 | 2404 | Port | Power grid SCADA |
| PROFINET | 34962-34964 | Port | Siemens / PROFIBUS International |
| MQTT | 1883, 8883 | Port | IIoT gateways |
| HART-IP | 5094 | Port | Process instrumentation |
| Foundation Fieldbus HSE | 1089-1091 | Port | Process automation |
| GE SRTP | 18245-18246 | Port + Signature | GE Automation PLCs |
| Wonderware SuiteLink | 5007 | Port + Signature | AVEVA / Wonderware |
Detection depth: Port = identified by TCP/UDP port number. Signature = matched by YAML payload/OUI patterns. Deep parse = full protocol dissection with function code analysis, device identification, and behavioral profiling.
| Platform | System Dependencies | Special Notes |
|---|---|---|
| Fedora/RHEL | libpcap-devel webkit2gtk4.1-devel libsoup3-devel javascriptcoregtk4.1-devel |
Primary dev platform |
| Ubuntu/Debian | libpcap-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf |
|
| macOS | brew install libpcap + Xcode CLI tools |
|
| Windows | VS C++ Build Tools + Npcap (WinPcap mode) + Npcap SDK | Set LIB env var to SDK Lib/x64 path |
sudo dnf install libpcap-devel webkit2gtk4.1-devel libsoup3-devel javascriptcoregtk4.1-devel
git clone https://github.com/TheSecurityLead/KusanagiNoKajiki.git
cd KusanagiNoKajiki
npm install
npm run build
npm run tauri dev # Development mode (hot-reload)
npm run tauri build # Production binary
Note: If
npm installfails with peer dependency errors on older npm versions, usenpm install --legacy-peer-depsas a fallback.
sudo apt install libpcap-dev libwebkit2gtk-4.1-dev \
libappindicator3-dev librsvg2-dev patchelf
git clone https://github.com/TheSecurityLead/KusanagiNoKajiki.git
cd KusanagiNoKajiki
npm install
npm run build
npm run tauri dev
brew install libpcap
xcode-select --install
git clone https://github.com/TheSecurityLead/KusanagiNoKajiki.git
cd KusanagiNoKajiki
npm install
npm run build
npm run tauri dev
Prerequisites (install in this order):
Visual Studio C++ Build Tools (required — Rust needs link.exe):
Rust (if not already installed):
stable-x86_64-pc-windows-msvcNpcap (required for packet capture):
C:\npcap-sdk[System.Environment]::SetEnvironmentVariable("LIB", "C:\npcap-sdk\Lib\x64", "User")
Node.js (LTS recommended): nodejs.org
Build steps (PowerShell):
git clone https://github.com/TheSecurityLead/KusanagiNoKajiki.git
cd KusanagiNoKajiki
npm install
npm run build
npm run tauri dev # development
npm run tauri build # production binary
If npm install fails with ERESOLVE peer dependency conflict:
The repo pins vite@^6.3.0 + @sveltejs/vite-plugin-svelte@^6.2.4. If you still get errors:
Remove-Item -Recurse -Force node_modules -ErrorAction SilentlyContinue
Remove-Item package-lock.json -ErrorAction SilentlyContinue
npm install -D vite@^6.3.0 @sveltejs/vite-plugin-svelte@^6.2.4 @sveltejs/kit@^2.16.0 @sveltejs/adapter-static@^3.0.8
npm install
npm run build
Do NOT run npm audit fix --force — it creates an infinite downgrade loop.
sudo setcap cap_net_raw,cap_net_admin=eip src-tauri/target/release/kusanaginokajiki
Open the Capture tab and click Import PCAP File(s). Multi-file selection is supported — each packet tracks its origin file.
Switch to the Topology tab. The logical view renders an interactive graph grouped by subnet. Right-click nodes to watch neighbors, create filtered views, or open in Wireshark. Use the timeline scrubber at the bottom to replay topology construction.
The Inventory tab shows all discovered assets with vendor identification, protocols, confidence scores, OUI vendor, country flags, and deep parse details. Click any asset to see Modbus/DNP3 function code analysis, register ranges, and polling intervals.
Navigate to the Analysis tab and click Run Analysis. The engine automatically:
Open the Export tab to generate:
# Open a PCAP file directly
kusanaginokajiki --open capture.pcap
# Open a session archive
kusanaginokajiki --open assessment.kkj
# Import a PCAP file on startup
kusanaginokajiki --import-pcap /path/to/capture.pcap
┌────────────────────────────────────────────────────────────┐
│ SvelteKit Frontend (Tauri Webview) │
│ ├── LogicalView (fcose + drift + timeline) │
│ ├── PhysicalView (switch/port Cytoscape) │
│ ├── MeshView (all-to-all mesh) │
│ ├── InventoryView (table + edit + detail + bulk) │
│ ├── CaptureView (import + live + sessions + ingest) │
│ ├── ProtocolStats (traffic + FCs) │
│ ├── SignatureEditor (YAML editor) │
│ ├── ExportView (CSV/JSON/PDF/SBOM/STIX) │
│ ├── AnalysisView (ATT&CK + Purdue + anomaly + drift) │
│ ├── TimelineScrubber (topology playback) │
│ └── SettingsView (theme + plugins + CLI) │
├────────────────────────────────────────────────────────────┤
│ Tauri IPC: 59 Commands + Event Streaming │
├────────────────────────────────────────────────────────────┤
│ Rust Backend (9 crates) │
│ ├── gm-capture Packet capture (pcap + etherparse) │
│ ├── gm-parsers Protocol ID + Modbus/DNP3 deep parse │
│ ├── gm-signatures YAML signature engine (25 signatures) │
│ ├── gm-topology Logical graph (petgraph) │
│ ├── gm-physical Cisco IOS config/CAM/CDP/ARP parsers │
│ ├── gm-ingest Zeek, Suricata, Nmap, Masscan import │
│ ├── gm-analysis ATT&CK, Purdue, anomaly scoring │
│ ├── gm-report PDF, CSV, JSON, SBOM, STIX export │
│ └── gm-db SQLite persistence, OUI, GeoIP │
└────────────────────────────────────────────────────────────┘
PCAP / Live Capture
→ gm-capture (L2-L4 parsing)
→ gm-parsers (protocol identification + deep parse)
→ gm-signatures (YAML pattern matching, confidence scoring)
→ gm-topology (petgraph network graph)
→ OUI / GeoIP enrichment
→ AppState
→ gm-analysis (ATT&CK + Purdue + anomaly detection)
→ gm-db (SQLite persistence)
→ gm-report (PDF / CSV / SBOM / STIX)
→ Frontend (Cytoscape topology, tables, charts)
Tauri 2.0, pcap, etherparse, petgraph, serde (JSON/YAML), tokio, thiserror, chrono, uuid, rusqlite (bundled SQLite), maxminddb, regex, quick-xml, genpdf, clap 4, zip.
SvelteKit (Svelte 5), TypeScript (strict), Cytoscape.js + fcose layout, Tailwind CSS 4, CodeMirror 6, @tauri-apps/api + plugins (dialog, shell).
# Run all 127 Rust tests
cd src-tauri && cargo test --all
# Strict clippy (zero warnings)
cargo clippy --all -- -D warnings
# Frontend type checking
cd .. && npm run check
# Full verification suite
npm run build && cd src-tauri && cargo test --all && cargo clippy --all -- -D warnings && cd .. && npm run check
Public ICS PCAP samples for testing:
npm install fails with ERESOLVE error:
Clean install with pinned versions — see Windows Installation section above. Do NOT use npm audit fix --force.
error: linker 'link.exe' not found during Rust compilation:
Install Visual Studio Build Tools with "Desktop development with C++" workload. VS Code is not sufficient. Restart your terminal after installation.
npm run build says 'vite' is not recognized:
npm install did not complete successfully. Fix dependency issues first, then re-run npm install and npm run build.
npm audit shows cookie vulnerability:
This is a low-severity server-side issue that does not affect Tauri desktop apps. Safe to ignore.
Npcap/libpcap linking errors on Windows:
Ensure Npcap is installed with "WinPcap API-compatible Mode" checked. Download Npcap SDK, extract it, and set LIB environment variable to include the SDK's Lib/x64 directory.
Contributions are welcome. Areas where contributions would be most valuable:
Apache License 2.0 — See LICENSE for details.
This is an independent project inspired by GRASSMARLIN. It contains no original GRASSMARLIN source code.