Skip to content

Releases: valinorintelligence/Gridwolf

Gridwolf v1.1.0 — Admin APIs, Helm chart, signed images

19 Apr 14:16

Choose a tag to compare

🎉 Gridwolf v1.1.0

Post-v1.0 release focused on operations, Kubernetes, and supply-chain security.


✨ New features

API key management — issue, list, and revoke long-lived API tokens. BLAKE2b-hashed at rest; the plaintext token is shown exactly once at creation.

System administration — live CPU / memory / disk / DB-size / uptime metrics plus per-table row counts via new /api/v1/system/* endpoints. Settings page auto-refreshes every 15 s.

Detection signature CRUD — YAML-based device-fingerprinting signatures with create, update, delete, and /test (YAML validation + live match counts).

Kubernetes Helm chartdeploy/kubernetes/helm/gridwolf with backend + frontend Deployments, bundled Postgres StatefulSet, Redis, Ingress, PVCs, and auto-generated secrets that survive upgrades via lookup().

helm install gridwolf ./deploy/kubernetes/helm/gridwolf \
  -n gridwolf --create-namespace \
  --set ingress.hosts[0].host=gridwolf.example.com

🔐 Supply-chain hardening

Every Docker Hub image is now:

  • Signed keyless via Sigstore cosign — no private key rotation, no public-key distribution.
  • Accompanied by SLSA provenance attesting to the build environment.
  • Accompanied by a CycloneDX SBOM listing every dependency.

Verify before pulling:

cosign verify gridwolf/backend:1.1.0 \
  --certificate-identity-regexp='^https://github.com/valinorintelligence/Gridwolf' \
  --certificate-oidc-issuer='https://token.actions.githubusercontent.com'

📄 New docs

  • SECURITY.md — vulnerability disclosure policy and response SLAs (required by AWS and Azure Marketplace security reviews).
  • DOCKER_HUB.md — condensed readme for the Docker Hub listing page.

🚀 Full deployment surface

Docker Compose → Docker Hub → OVA → AWS CloudFormation → Azure Bicep → Kubernetes Helm → source build.


Upgrade notes

  • The admin user is unchanged. No database migration needed — new tables (api_keys, signatures) are created automatically by init_db on first boot of v1.1.0.
  • Operators upgrading Helm: existing secrets are preserved via lookup() so GRIDWOLF_SECRET_KEY is stable across helm upgrade.

Full changelog: v1.0.0...v1.1.0

v1.0.0 — Production Release

19 Apr 05:03

Choose a tag to compare

Gridwolf v1.0.0 — Production Release 🎉

First stable release. All pages wired to real API, all deployment targets ready.


🚀 Quick Start (Docker Hub)

curl -O https://raw.githubusercontent.com/valinorintelligence/Gridwolf/main/docker-compose.hub.yml
curl -O https://raw.githubusercontent.com/valinorintelligence/Gridwolf/main/.env.example
cp .env.example .env   # set GRIDWOLF_SECRET_KEY and POSTGRES_PASSWORD
docker compose -f docker-compose.hub.yml up -d
# → http://localhost

🔑 First-run admin password

On a fresh install, the admin password is auto-generated and printed once to the backend log:

docker compose -f docker-compose.hub.yml logs backend | grep -A1 "Password"

📦 Deployment options

Method File
Docker Hub docker-compose.hub.yml + .env.example
OVA (VMware / VirtualBox) packer/gridwolf.pkr.hcl — see README
AWS CloudFormation deploy/aws/gridwolf.template.yaml
Azure Bicep deploy/azure/gridwolf.bicep

Full instructions: README → Installation


What's in v1.0.0

Backend

  • GET /health — deep health check (probes DB); returns HTTP 503 when DB is unavailable; includes version, uptime_seconds, database fields — compatible with AWS ELB, Azure LB, and Docker health probes
  • GET /version — machine-readable version endpoint used by OVA wizard and AMI UserData scripts
  • First-run admin seeding — creates admin account on startup if users table is empty; auto-generates a secure random password printed once to stdout; fully idempotent
  • GRIDWOLF_SECRET_KEY now required in production — startup exits with a clear error message instead of silently auto-generating an insecure key
  • App version reads from settings.APP_VERSION (was hardcoded "0.1.0")

Deployment infrastructure (v0.9.9)

  • Docker Hub CI via GitHub Actions (linux/amd64 + linux/arm64)
  • OVA build via HashiCorp Packer + VirtualBox + Ubuntu 24.04
  • First-boot wizard with IP detection, password setup, secret generation
  • AWS CloudFormation template (EC2 + EIP + encrypted EBS + IAM)
  • Azure Bicep template (VM + static IP + Premium_LRS disks + NSG)

Security (v0.9.9)

  • Hardcoded secrets removed from Dockerfile.backend
  • Nginx gzip compression, immutable asset cache, X-XSS-Protection
  • docker-compose.prod.yml aborts if secrets are missing

v0.9.9 — OVA · Docker Hub · AWS · Azure deployment infrastructure

19 Apr 04:21

Choose a tag to compare

v0.9.9 — Full Deployment Infrastructure

🔴 Phase 0 — Security blockers fixed

File Fix
Dockerfile.backend Removed hardcoded GRIDWOLF_SECRET_KEY and DATABASE_URL — no secrets baked into image
config.py Production start now exits with a clear error if GRIDWOLF_SECRET_KEY is not explicitly set; auto-gen only in DEBUG=true with a loud warning
docker-compose.prod.yml POSTGRES_PASSWORD and GRIDWOLF_SECRET_KEY use :? syntax — Compose aborts with a descriptive message if either is unset
nginx.conf Gzip compression, immutable cache headers for Vite assets, no-cache on index.html, X-XSS-Protection header, proxy_buffering off

🐳 Phase 1 — Docker Hub quick-start

curl -O https://raw.githubusercontent.com/valinorintelligence/Gridwolf/main/docker-compose.hub.yml
curl -O https://raw.githubusercontent.com/valinorintelligence/Gridwolf/main/.env.example
cp .env.example .env   # set GRIDWOLF_SECRET_KEY and POSTGRES_PASSWORD
docker compose -f docker-compose.hub.yml up -d
# → open http://localhost

GitHub Actions CI (.github/workflows/docker-hub.yml):

  • Triggers on every v*.*.* tag
  • Builds linux/amd64 + linux/arm64 for both backend and frontend
  • Pushes gridwolf/backend:<version> and gridwolf/frontend:<version> to Docker Hub
  • Appends Docker Hub install block to the GitHub release notes automatically

💿 Phase 2 — OVA (VMware ESXi / Workstation / VirtualBox)

Packer build (packer/gridwolf.pkr.hcl):

  • Ubuntu 24.04 LTS minimal → VirtualBox → .ova export
  • Docker CE + Compose pre-installed
  • Gridwolf images pre-pulled (air-gap capable)
  • First-boot wizard auto-detects IP, sets admin password, generates secrets, starts services

GitHub Actions (.github/workflows/build-ova.yml):

  • Runs automatically after Docker Hub push succeeds
  • Attaches gridwolf-<version>-amd64.ova.gz to this release

☁️ Phase 3 — AWS Marketplace / CloudFormation

deploy/aws/gridwolf.template.yaml:

  • Single EC2 instance (t3.medium → c5.4xlarge selectable)
  • Elastic IP, encrypted gp3 EBS data volume (retained on stack delete)
  • Security group (80/443/22), IAM CloudWatch role
  • UserData bootstraps Docker + secrets + Gridwolf on first boot
  • Outputs: public IP, web UI URL, API docs URL, SSH command

🔷 Phase 4 — Azure Marketplace / Bicep

deploy/azure/gridwolf.bicep:

  • Standard_D2s_v3 default VM (B2s → F4s_v2 selectable)
  • Static public IP with auto-generated FQDN
  • Premium_LRS OS + data disks (both encrypted at rest)
  • NSG (80/443/22), VNet, cloud-init bootstraps Gridwolf
  • Outputs: public IP, FQDN, web UI URL, SSH command
az group create -n gridwolf-rg -l eastus
az deployment group create \
  -g gridwolf-rg \
  -f deploy/azure/gridwolf.bicep \
  -p adminPasswordOrKey='<ssh-pub-key>' gridwolfVersion='v0.9.9'

⚙️ Next steps before first marketplace submission

  1. Create Docker Hub account gridwolf and add DOCKERHUB_USERNAME + DOCKERHUB_TOKEN to GitHub repo secrets — the CI pipeline is ready to fire
  2. Push v0.9.9 tag (already done) → Docker Hub workflow triggers automatically
  3. Run packer build locally to produce the first .ova and verify the first-boot wizard
  4. Create AWS Marketplace seller account and submit CloudFormation template
  5. Enroll in Microsoft Partner Center and submit Bicep template

v0.9.8 — Production API wiring & security hardening

18 Apr 22:05

Choose a tag to compare

What's New in v0.9.8

🔴 Security Fixes

  • Path traversal fix (pcap.py): Upload filenames sanitised with Path(filename).name — prevents ../ traversal attacks
  • XSS fix (report_generator.py): All user-controlled values (IPs, finding titles, client names) HTML-escaped in generated reports via html.escape()
  • DoS fix (sessions.py): Unbounded SQL queries replaced with limit/offset pagination on all list endpoints

🟠 React Bug Fixes

  • NetworkTopology: Replaced 8 module-level mutable let globals with useState<TopologyData> — eliminates stale data on remount
  • CommandCenter: Fixed criticalCount fallback logic, null edges crash, and spurious severity: undefined API param
  • TimelineView: Fixed Math.min(...[])Infinity crash on empty dataset
  • Routes: advisory-detail now includes :id dynamic param

🟡 Hardcoded Mock Data Removed

All pages now fetch real data from the backend API:

Page Was Now
ThreatIntelligence Fake IPs, hardcoded ATT&CK counts /ics/findings/mitre_technique mapping populates matrix
AdvisoryDetail Static advisory object useParams(:id)/ics/advisories/${id} + matched devices
MyEnvironment Hardcoded matched advisories preview /ics/advisories/matched; Save POSTs to /ics/advisories/environment
ReportDiff Hardcoded snapshots and diff nodes /ics/sessions/ + /ics/devices/?session_id=X; diff computed client-side
Integrations Hardcoded import history table /ics/pcap/list for real PCAP upload history
MetricsAnalytics 6 static chart arrays /ics/devices/stats + /ics/findings/stats
Compliance Hardcoded IEC/NIST/NERC scores Derived from real findings via finding_type → framework mapping
ProtocolAnalyzer Fake Modbus/S7 tables /ics/devices/stats + /ics/devices/ filtered by protocol

TypeScript

Zero type errors (npx tsc --noEmit clean).

Gridwolf v0.9.5 — Production Audit & Security Hardening

13 Apr 07:18

Choose a tag to compare

Production Audit — Pre-OVA Release

Full codebase audit (42 backend files, 96 frontend files, all deployment configs) with fixes applied.

Security Hardening (Critical)

Fix Before After
CORS allow_origins=["*"] (any website) Configured origins only (localhost:3000, etc.)
SECRET_KEY Hardcoded "gridwolf-dev-secret-key..." Auto-generated 64-byte random key if not set via env
WebSocket No authentication JWT token required via ?token= query param
Password Only min_length=8 Requires uppercase + lowercase + digit
DEBUG True by default False by default
JWT Expiry 24 hours 12 hours
nginx No security headers X-Frame-Options, X-Content-Type-Options, Referrer-Policy

Remaining Mock Data Removed

Page What was removed Replaced with
PcapImport RECENT_IMPORTS (5 fake entries) Real data from GET /ics/pcap/list
SecurityScorecard OVERALL_SCORE, CATEGORY_SCORES, TREND_DATA Computed from real /ics/findings/stats + /ics/devices/stats
ReportGenerator SESSIONS[], GENERATED_REPORTS[] Real data from /ics/sessions/ + /ics/findings/reports/list
ExportHub FIREWALL_RULES, REMEDIATION_LIST Real findings from /ics/findings/

Bug Fixes

  • auth.ts service: Was posting form-encoded to /auth/token (non-existent endpoint) — fixed to JSON POST to /auth/login
  • auth.ts register: Was sending fullName — backend expects full_name
  • useWebSocket: Was using wrong localStorage key (token instead of gridwolf_token), hardcoded ws://localhost:8000 — now uses dynamic URL with auth token
  • docker-compose.yml: Health check was hitting /docs instead of /health
  • docker-compose.prod.yml: Frontend build context was wrong (./frontend instead of . for npm workspaces), missing health checks, missing restart policies, hardcoded secrets
  • nginx.conf: WebSocket proxy had no timeouts — added 86400s for long-lived connections, added /health proxy

Docker Deployment

docker compose up --build
# UI: http://localhost:3000  |  API: http://localhost:8000/docs

Audit Summary

Category Issues Found Fixed
Critical (security) 6 6
High 8 5
Medium 5 3
Low 3 2

Remaining high/medium items (deferred to OVA build phase): rate limiting, Celery task queue, comprehensive test suite, OUI database expansion, request ID logging.

Gridwolf v0.9.4 — Real Data Only, No Mock Data

12 Apr 18:28

Choose a tag to compare

What's New in v0.9.4

Mock Data Removed — All Pages Wired to Real Backend

All 14 frontend pages now fetch exclusively from the real /api/v1 backend. Zero hardcoded or dummy data remains in the product.

Pages updated:
CommandCenter, DeviceInventory, NetworkTopology, Timeline, OntologyExplorer, ObjectDetailPage, RelationshipGraphPage, PurdueModel, AttackPaths, ScanImport, SBOM, SLATracker, AssetInventory

What changed:

  • Deleted mock.ts (670 lines of fake data) and unused PcapImport component
  • Every page shows a loading spinner while fetching, and a clean empty state when no data exists
  • All dashboard widgets, tables, charts, and topology graphs render real data only

Authentication & Registration Fixed

  • Registration now calls the real /auth/register endpoint (was incorrectly falling into demo mode)
  • Login posts JSON to /auth/login (was sending form-encoded data to non-existent /auth/token)
  • Fixed React hooks ordering crash (error #300) after login
  • Fixed snake_case → camelCase user field mapping between backend and frontend

Docker Build Fixed

  • Dockerfile.frontend now works with npm workspaces (copies root lock file correctly)
  • docker-compose.yml build context fixed so nginx.conf is accessible
  • Pinned bcrypt>=4.0.0,<5.0.0 to fix passlib incompatibility

Docker Deployment

docker compose up --build
# UI: http://localhost:3000  |  API: http://localhost:8000/docs

Test credentials: testuser / Test1234! or demo / demo1234

Verified End-to-End

Test Result
Register new user
Login with real credentials
Upload PCAP → devices discovered ✅ (177 devices)
Upload PCAP → findings generated ✅ (12,326 findings)
Command Center dashboard ✅ Real stats, charts, tables
Device Inventory ✅ Real device list with search/filter
All other pages ✅ Empty states or real data

PCAP Test Results

PCAP File Format Packets Protocols Detected
Plant1.pcap pcap 55,800 Modbus, S7comm, EtherNet/IP, DSATP
bacnet_test.pcap pcap 26 BACnet
addroute.pcapng pcapng 246 Beckhoff ADS
modbus.pcap pcap 60,227 Modbus

Gridwolf v0.9.3 — PCAP Analysis Fix

11 Apr 12:52

Choose a tag to compare

Bug Fixes

PCAP Upload: Results now display correctly after processing

  • Root cause: The background PCAP processing task was async but called synchronous Scapy parsing, which blocked the entire FastAPI event loop. This made the server unresponsive during processing, causing frontend status polls to fail or timeout — resulting in users seeing nothing after uploading a PCAP.
  • Fix: PCAP processing now runs in a thread pool (asyncio.to_thread()), keeping the event loop responsive.

PCAP file upload corruption & format support

  • Fixed Content-Type header conflict (explicit multipart/form-data without boundary corrupted uploads)
  • Added server-side magic byte validation before Scapy processing (pcap LE/BE, nanosecond, pcapng)
  • Added pcapng reader support (PcapNgReader with rdpcap fallback)
  • Fixed state duplication bug when PcapReader failed and fell back to rdpcap
  • Added nginx client_max_body_size 500M and extended proxy timeouts for large files

Docker build fix

  • Fixed Dockerfile.frontend to work with npm workspaces (lock file at root, not in frontend/)
  • Fixed docker-compose.yml build context so nginx.conf is accessible during build
  • Both containers now build and run correctly with docker compose up --build

Authentication & Registration

  • Fixed registration flow: was always going to demo mode, now correctly calls /auth/register for real backend
  • Fixed login: was posting form-encoded to non-existent /auth/token, now posts JSON to /auth/login
  • Fixed React hooks ordering crash (error #300) on real backend login
  • Fixed snake_case → camelCase user field mapping

Removed all mock/dummy data

  • Deleted mock.ts (670 lines of hardcoded fake data) and unused PcapImport component
  • Rewired all 14 pages to fetch from real /api/v1 backend endpoints
  • Pages show loading spinners and empty states when no data is available
  • All dashboard widgets, tables, charts, and graphs now display real data only

Protocol identification improvements

  • Fixed dead Modbus heuristic code (port-based check duplicated the ICS_PORTS lookup, so payload heuristics never ran for non-standard Modbus ports)
  • Added proper payload validation for all protocol heuristics (Modbus length field, TPKT length, APDU length, BVLC type)
  • Added BACnet/IP payload-based detection for traffic on non-standard ports

Frontend polling resilience

  • Polling now retries up to 5 consecutive errors before giving up (previously failed on the first error)
  • Added 3-minute max timeout for large PCAPs
  • Fixed potential race condition with overlapping poll callbacks
  • Added cleanup of poll interval on component unmount

New ICS Protocol Port Mappings

Protocol Ports Added
Modbus TCP 503, 802
S7comm / SIMATIC NET 5026
DNP3 19999
PROFINET RT 34962, 34963, 34964
FOUNDATION Fieldbus HSE 1089, 1090, 1091
GE SRTP / GDS 18245
DSATP (Emerson/Fisher) 2111

Docker Deployment

docker compose up --build
# UI: http://localhost:3000  |  API: http://localhost:8000/docs

Default login: demo / demo1234

Tested With (Docker end-to-end)

PCAP File Format Packets Protocols Detected
Plant1.pcap pcap 55,800 Modbus, S7comm, EtherNet/IP, DSATP
bacnet_test.pcap pcap 26 BACnet
addroute.pcapng pcapng 246 Beckhoff ADS
modbus.pcap pcap 60,227 Modbus

v0.3.0 — Real PCAP Analysis Wired to Backend

10 Apr 23:38

Choose a tag to compare

v0.3.0 — Real PCAP Analysis

What's Fixed

PCAP upload now actually works in self-hosted mode.

Previously the frontend only showed a fake animation — the file was never sent to the backend. Now:

  • Uploads PCAP to POST /api/v1/ics/pcap/upload
  • Polls GET /api/v1/ics/pcap/status/{id} every 2s until complete
  • Fetches real discovered devices and security findings from backend
  • Displays actual results: device inventory, MITRE ATT&CK findings, protocol breakdown
  • Shows error message if processing fails

Demo Site (GitHub Pages)

Still works with simulated results — no backend needed:
https://valinorintelligence.github.io/Gridwolf/

Self-Hosted (Full Backend)

git clone https://github.com/valinorintelligence/Gridwolf
cd Gridwolf
docker compose up --build

Drop a real PCAP → get real ICS device discovery + security findings.

v0.2.0 — Live Demo Fix & GitHub Pages Deployment

07 Apr 12:31

Choose a tag to compare

What's New in v0.2.0

Bug Fixes

  • Fixed demo auth flow: Users who register or log in with any credentials on the live demo site are now correctly logged in as the demo user — no more "invalid credentials" error
  • Fixed logo not loading on GitHub Pages (was using absolute path /logo.png instead of base-relative path)
  • Fixed sample PCAP and report download paths for GitHub Pages deployment

New Features

  • Live Demo Site: https://valinorintelligence.github.io/Gridwolf/ — explore all 30+ dashboards instantly, no install needed
  • Demo mode banner: Clear amber banner on Login and Register pages explaining demo mode behavior
  • GitHub Pages deployment: Automated via GitHub Actions on every push to main

How to Use the Live Demo

  1. Visit https://valinorintelligence.github.io/Gridwolf/
  2. Click Demo Login — or enter any email/password (both work in demo mode)
  3. Explore 30+ ICS/OT security dashboards with pre-loaded data

Self-Hosted (Full Backend)

git clone https://github.com/valinorintelligence/Gridwolf
cd Gridwolf
docker compose up --build

Access at http://localhost:3000 with real PCAP processing and backend.