Open-source platform for NIS2 Directive (EU 2022/2555) continuous posture management. Governance framework, technical validation engine, remediation playbooks, incident response workflows, and supply chain risk management.
Designed for self-hosted, on-premise deployment. Your scan data, asset inventory, and vulnerability reports never leave your infrastructure.
For CISO, DPO, NIS2 consultants, and IT teams bridging the gap between compliance documentation and operational execution.
This is not a scanner that calls itself a compliance platform. It's a GRC layer with an integrated technical validation engine. It does not replace a CISO, an internal audit programme, or a real legal review of your D.Lgs 138/2024 obligations.
| Layer | What it does |
|---|---|
| Governance Framework | 30-item checklist cross-referenced to NIS2 Art. 21 sub-paragraphs, document tracking, owner assignment |
| Remediation and Execution Control | Structured playbooks, optional AI copilot (Ollama/OpenAI), open/acknowledged/resolved workflow |
| Technical Validation Engine | 30+ automated checks (TLS, DNS, ports, certificates, headers, secrets) — the probe that verifies if the network reflects the policy |
The scanner is the technical probe. The governance framework is where the substantive NIS2 work lives — and most of it is human work, not automation.
The compliance matrix references all ten sub-paragraphs (a) through (j). Several of them — by design of the directive itself — cannot be evaluated by an automated scanner and are tracked through the governance checklist (status: manual verification required). What the platform automates vs. what stays manual:
| Sub-paragraph | Scope | Implementation status | How the platform supports it |
|---|---|---|---|
| (a) Risk analysis policies | Methodology, periodic updates | Partial — automated bridge from scanner findings | Governance checklist + POST /governance/sync-risk automatically escalates checklist items when HIGH/CRITICAL scanner findings are open; risk summary via GET /governance/risk-summary |
| (b) Incident handling | Detection, response, CSIRT notification | Implemented — automated deadline enforcement | Incident module + Art. 23 lifecycle + Celery beat task checks every 15 min and dispatches alerts (email/webhook/Slack) at 24 h / 72 h / 1-month thresholds with Redis-backed dedup |
| (c) Business continuity | BCP, DRP, backup, periodic testing | Implemented — manual verification | BIA module (RTO/RPO/MTPD), impact scoring, gap detection |
| (d) Supply chain security | Vendor assessment, contracts, monitoring | Implemented — transparent scoring formula | Vendor Risk module (Art. 18) with documented 100-point scoring formula (certification, data access, audit recency, geography, security clauses); auditor-facing GET /vendors/score-formula |
| (e) Secure acquisition and development | SDLC, code review, vulnerability management | Partial — scanner automates surface checks | Technical validation engine (TLS, headers, secrets, ports) + governance checklist for organisational controls |
| (f) Effectiveness assessment | Internal audits, KPIs, penetration testing | Partial — scan-driven | Technical validation engine + checklist |
| (g) Cyber hygiene and training | Awareness, phishing simulation | Manual | Governance checklist (human verification required by design) |
| (h) Cryptography | Crypto policy, key management | Partial — automated for public-facing TLS | Technical validation (TLS version, cipher suites, cert expiry, HSTS) + checklist for key-management policy |
| (i) Human resources security | Onboarding/offboarding, screening, PAM | Manual | Governance checklist (human verification required by design) |
| (j) Authentication and access control | MFA, RBAC, PAM, SSO, access logging | Implemented — TOTP MFA, RBAC, audit log, API key scopes | TOTP MFA (POST /auth/totp/setup|verify|disable), MFA-gated login flow, role-based access (owner/admin/auditor/viewer), per-request scoped API keys (dual_auth_with_scope), per-request audit log, RS256 JWT with GET /.well-known/jwks.json |
Legend: Implemented = fully automated with no manual step required. Partial = automated checks cover the technically observable surface; organisational controls require human verification. Manual = the directive explicitly requires human judgement — automation cannot substitute.
Incident lifecycle aligned with the legal deadlines:
| Phase | Deadline | Platform support |
|---|---|---|
| Early Warning | 24 hours | "Red Button" generates a CSIRT-ready Early Warning JSON + automated alert 2 h before / on breach via email, webhook (HMAC-SHA256 signed), or Slack |
| Incident Notification | 72 hours | Structured form with taxonomy, IOCs, timeline + automated alert 2 h before / on breach |
| Final Report | 1 month | Aggregated data, impact assessment, lessons learned + automated alert 2 h before / on breach |
Note: The platform produces the artefacts, tracks the deadlines, and dispatches alerts automatically via configured notification channels. Submission to CSIRT Italia is a manual step through
csirt.gov.it. There is no automated push to the CSIRT portal.
| Feature | Status |
|---|---|
| Vendor inventory with criticality classification (1-4) | Implemented |
| Security assessment scoring (0-100) | Implemented |
| Contract tracking (SLA, audit rights, security clauses) | Implemented |
| Geographic location and data access level | Implemented |
| Certification tracking (ISO 27001, SOC2, CSA STAR) | Implemented |
| ACN Art. 18 relevance flagging (Italy) | Implemented |
| Feature | Status |
|---|---|
| Business process inventory with criticality levels | Implemented |
| RTO/RPO/MTPD definition per process | Implemented |
| 5-dimension impact scoring (financial, operational, reputational, regulatory, safety) | Implemented |
| Asset and vendor dependency mapping | Implemented |
| BCP/DRP gap detection | Implemented |
| Impact matrix with automatic gap identification | Implemented |
The NIS2 Directive requires each EU member state to transpose it into national law. This platform provides a reference implementation for Italy, extensible to other jurisdictions.
| Reference | Coverage |
|---|---|
| D.Lgs 138/2024 (Italian NIS2 transposition) | Art. 21 cross-reference in the governance checklist |
| Determina ACN 127434/2026 | Technical baseline references in the compliance matrix |
| Determina ACN 127437/2026 | Art. 18 vendor inventory with ACN-specific fields |
| ACN BIA template | Internal model in place; alignment to the official ACN model pending publication |
| Compliance deadlines API | Real countdowns: CSIRT referent (Dec 2026), 24h notification (Jan 2027), baseline measures (Jul 2027) |
| ACN-compatible JSON export | /api/v1/acn-export/art18 and /api/v1/acn-export/bia |
ACN export — preliminary schema. The official modello di categorizzazione announced by ACN (publication expected May/June 2026 per the Tavolo NIS) has not been released yet. The current export is a best-effort structural mapping based on Determina 127437/2026; field names and shape will be re-validated and may change once the official template is published.
The governance checklist maps to NIS2 Art. 21 at the EU level. National-specific modules (like the Italian ACN module) can be added for ANSSI (France), BSI (Germany), CCN-CERT (Spain) and others — contributions welcome.
A CISO of an essential entity will not upload their vulnerability data to a third-party cloud. This platform is designed to run inside your perimeter.
| Tool | Why | Notes |
|---|---|---|
| Docker + Docker Compose v2.20+ | Runs the API, web, scanner, postgres, redis, celery containers | compose v2.20 is required for --wait on healthchecks (make dev / make prod rely on it) |
| GNU Make | Drives the standardised targets (dev, prod, clean, test, etc.) |
Pre-installed on macOS / Linux. On Windows: install via Git Bash, WSL2, or Chocolatey |
| Python 3.10+ on the host | Used by make clean, make clean-all, and make test-* (pytest) |
Linux/macOS package manager works; on Windows install from python.org (the Microsoft Store stub at %LOCALAPPDATA%\Microsoft\WindowsApps\python.exe is not a real Python — disable that alias in Settings → Apps → Apps & Features → App execution aliases). The Makefile detects python3 / py / python in that order. |
openssl (or any random-bytes generator) |
Generates JWT_SECRET and NEXTAUTH_SECRET for production deploys |
openssl rand -base64 32 is the canonical recipe |
The platform itself runs inside containers and pulls all its runtime deps from the images — Node, Postgres, Redis, the Python interpreter for the API, etc. The host-side prerequisites above only drive build / clean / test from the Makefile.
git clone https://github.com/fabriziosalmi/nis2-public.git
cd nis2-public
cp .env.example .env # Generate real secrets — see comments inside
make prod # Production: Caddy auto-HTTPS + all services
# Or development:
make dev # http://localhost:8077 (UI) + http://localhost:8000/docs (API)All data stays in your PostgreSQL instance. No telemetry, no external calls, no cloud dependencies.
make prod runs a pre-flight check (prod-preflight) before bringing up the stack. If .env is missing or carries placeholder values for POSTGRES_PASSWORD / JWT_SECRET / CORS_ORIGINS, the target exits early with a self-contained error message describing the exact command to fix it. The minimum recipe to put .env into a runnable shape:
# Postgres password — any non-empty string; rotate before sharing infra
sed -i.bak 's|^POSTGRES_PASSWORD=.*$|POSTGRES_PASSWORD='$(openssl rand -base64 24)'|' .env
# JWT secret — must be ≥32 chars; the API refuses to start otherwise
sed -i.bak 's|^JWT_SECRET=.*$|JWT_SECRET='$(openssl rand -base64 32)'|' .env
# NextAuth secret
sed -i.bak 's|^NEXTAUTH_SECRET=.*$|NEXTAUTH_SECRET='$(openssl rand -base64 32)'|' .env
# Redis password
sed -i.bak 's|^REDIS_PASSWORD=.*$|REDIS_PASSWORD='$(openssl rand -base64 24)'|' .env
# CORS allow-list — comma-separated, no wildcards. Example:
sed -i.bak 's|^CORS_ORIGINS=.*$|CORS_ORIGINS=https://nis2.example.com|' .env
rm -f .env.bak(macOS users: that's GNU sed syntax. For BSD sed drop the .bak argument or use a different editor — the goal is "replace the placeholder line with a real secret".)
For air-gapped environments: Ollama AI copilot runs entirely local.
These automated checks verify whether the security measures documented in your governance framework are actually implemented on the network:
| Category | Checks |
|---|---|
| Certificates | Chain validation, CT log monitoring (crt.sh), OCSP, key strength (RSA/ECDSA), SAN coverage, expiry prediction, health scoring 0-100 |
| TLS/SSL | Protocol versions, cipher suites, weak protocols, HSTS enforcement |
| DNS security | DNSSEC, SPF, DMARC, DKIM, zone transfer protection, MX redundancy |
| HTTP headers | CSP, X-Frame-Options, cookie flags, SRI, security.txt |
| Port exposure | 14 critical ports (SSH, RDP, SMB, MySQL, PostgreSQL, Redis, MongoDB) |
| Resilience | WAF/CDN detection, version disclosure, SSH hardening |
| Secrets | AWS keys, GitHub tokens, private keys, JWT in responses |
These checks verify GDPR / ePrivacy / Consumer Code requirements. They are not NIS2 controls and are clearly labelled as such in all reports — never aggregated into the NIS2 score.
- P.IVA (Italian commercial website requirement)
- Privacy policy detection
- Cookie banner compliance (via Playwright)
| Router | Endpoints | Purpose |
|---|---|---|
/api/v1/auth |
13 | JWT authentication, registration, change-password, forgot/reset password, switch active organization, TOTP setup/verify/disable |
/api/v1/scans |
8 | Scan management, results, comparison. Read endpoints accept API-key Bearer auth |
/api/v1/findings |
5 | Finding lifecycle (open/acknowledged/resolved). Read endpoints accept API-key Bearer auth |
/api/v1/assets |
6 | Asset inventory management. Read endpoints accept API-key Bearer auth |
/api/v1/api-keys |
3 | Long-lived nis2_* Bearer tokens for CI/CD pipelines (raw value shown once) |
/api/v1/audit-logs |
1 | Read-only org-scoped audit trail (90-day retention) |
/api/v1/organizations |
8 | Org settings, members, role management, self-serve org creation |
/api/v1/vendors |
5 | Vendor risk management (Art. 18) |
/api/v1/bia |
5 | Business Impact Analysis |
/api/v1/incidents |
6 | Incident lifecycle (Art. 23 CSIRT) |
/api/v1/governance |
4 | 30-item Art. 21 checklist |
/api/v1/certificates |
3 | Deep certificate analysis |
/api/v1/remediation |
4 | Playbooks, AI copilot, cost estimation |
/api/v1/acn-export |
2 | ACN-compatible JSON export (Italy, preliminary schema) |
/api/v1/deadlines |
1 | Compliance deadline countdown |
/api/v1/csirt/emergency |
1 | "Red Button" — instant Early Warning payload |
/api/v1/mcp |
2 | Model Context Protocol for AI assistants |
/.well-known/jwks.json |
1 | RS256 public key set for JWT verification |
/.well-known/security.txt |
1 | Responsible disclosure contact |
/health, /health/live, /health/ready |
3 | Three-tier liveness / readiness (DB + Redis + Celery) |
Designed for NIS2 consultants and DPO-as-a-service managing multiple clients:
- Organization-based data isolation (
organization_idfilter on every protected query, enforced by PostgresFORCE ROW LEVEL SECURITYpolicies — even the table owner cannot bypass them) - RBAC: admin, auditor, viewer per organization
- Org switcher in the sidebar — a user with memberships in multiple orgs can move between client tenants without logging out (
POST /api/v1/auth/switch-orgremints the JWT with the neworg_idclaim, the FE clears the TanStack Query cache so no stale data leaks, audit log records the transition) - Self-serve org creation — the switcher dropdown has a "Create new organization" footer entry that opens a dialog: enter a name, the API derives a unique slug, the user lands as
accepted_at-stamped admin in the new tenant, and the FE auto-switches into it (POST /api/v1/organizations) - Executive PDF/CSV reports per client
- Aggregated compliance dashboard across all organizations
- Each client's data stays in the same self-hosted instance
| Layer | Technology |
|---|---|
| Frontend | Next.js 15, React 19, shadcn/ui, Tailwind v4, Zustand, TanStack Query, Recharts, next-intl |
| Backend | FastAPI, SQLAlchemy (async), Pydantic v2, Celery, Redis, slowapi |
| Database | PostgreSQL 16 |
| Scanner | Python asyncio, aiohttp, dnspython, Playwright, python-whois |
| Security | CSP/HSTS/X-Frame-Options at the proxy and API layers, rate limiting (SlowAPI), SSRF prevention, API key auth, TOTP MFA, RS256 JWT + JWKS, RLS row-level isolation, audit log retention (90 days) |
| AI / MCP | MCP Server (stdio + HTTP), Ollama/OpenAI |
| Infra | Docker, Caddy 2 (auto-HTTPS), GitHub Actions CI |
| English | Italiano | Français | Deutsch | Español |
|---|
189 translation keys across 5 locales. Cookie-based locale switching.
Platform developed and maintained by Fabrizio Salmi, independent NIS2 consultant.
| Service | Description |
|---|---|
| Private NIS2 scan | White-label scan with executive report for the board |
| Certificate remediation | TLS/SSL lifecycle with CertMate and CertMate-NG |
| NIS2 readiness assessment | Gap analysis on all 10 Art. 21 sub-paragraphs |
| Incident response | CSIRT Art. 23 notification support, taxonomy, timeline |
| Continuous monitoring | Scheduled scans, trend analysis, quarterly reports |
| Platform customization | Private deploy, sector modules, SIEM/SOAR integration |
| Training | Board-level NIS2 overview, technical training for IT teams |
Contact: fabrizio.salmi@gmail.com
Related tools: CertMate | CertMate-NG (private — request access)
The 30-item Art. 21 governance checklist shipped with the platform is a community-curated didactic heuristic, not a verbatim reproduction of the official ACN framework. The Italian National Cybersecurity Agency (Agenzia per la Cybersicurezza Nazionale — ACN) has translated the ten NIS2 risk-management measures into a NIST-derived control set detailed across multiple Determinazioni (e.g. Determina 127434/2026, 127437/2026, and follow-ups). The checklist included here is a starting point that maps to the ten Art. 21(2) sub-paragraphs at a high level and references the relevant ACN determinazioni; it does not, and is not intended to, replace a formal ACN-grade audit, a Modello di Categorizzazione filing, or any other regulatory deliverable.
The technical validation engine performs automated checks on publicly-observable surface (TLS, DNS, HTTP headers, port exposure, etc.) — these correspond to a subset of Art. 21(2)(h) "cryptography" and Art. 21(2)(e) "security in network and information systems acquisition" controls. They do not validate organisational controls (risk-management policies, incident-response procedures, supply-chain contracts, HR processes, training records, etc.) which by directive design require human verification.
This platform is a tool for governance and discovery, not legal or compliance advice. Engagement with a qualified NIS2 advisor and direct reference to ACN guidance remain mandatory for any production compliance posture.
In compliance with Art. 7-12 of D.Lgs 70/2003 (Italian e-commerce decree) and the EU e-Commerce Directive 2000/31/EC:
- Operator: Salmi Fabrizio (sole proprietor / libero professionista)
- Registered address: Via Sapri 9, 16134 Genova, Italy
- VAT (P.IVA): IT 03072120995
- ATECO code: 62.10.00 (Computer programming activities)
- Tax regime: Regime semplificato
- Contact: fabrizio.salmi@gmail.com
- Privacy: see docs/privacy.md for the GDPR Art. 13 information notice covering the public website, the documentation site, and any direct contact via the channels above.
Self-hosted deployments: when you run this platform on your own infrastructure, you become the data controller under Art. 4(7) GDPR for the personal data processed by your instance (registered users, scan results, asset inventory, audit logs). The maintainer is not the data controller for self-hosted instances and provides no
informativa privacyon your behalf. Adapt docs/privacy.md to your deployment, publish it at a stable URL, and notify your users.
AGPL-3.0 — see LICENSE.
You can freely use, modify, and deploy this platform. If you modify it and offer it as a service to third parties, you must make your modifications available under the same license.
Commercial license / dual licensing available for Enterprise. If your organization needs a commercial license without copyleft obligations, contact fabrizio.salmi@gmail.com.
