Commit Graph

6 Commits

Author SHA1 Message Date
vulncheck ec81ec609f feat(nessus): schema + model for multi-source vuln tracking
Migration 010 + model updates that prep VulnCheck to merge Nessus
findings with existing Wazuh-sourced vulnerabilities on the same
(cve_id, asset_id) row instead of creating parallel duplicates.

Schema (alembic/versions/010_add_nessus_integration.py):
- vulnerabilities.sources           JSON list of scanners that detected
                                    this finding, e.g. ["wazuh","nessus"]
- vulnerabilities.nessus_plugin_id  Nessus plugin ID for the finding
- vulnerabilities.nessus_finding_uuid stable per-finding identifier
- vulnerabilities.first_detected_by which scanner first reported it
- vulnerabilities.cve_id widened    20 -> 50 chars so non-CVE Nessus
                                    findings can be stored as
                                    NESSUS-PLUGIN-{plugin_id} pseudo-CVEs
- assets.nessus_host_uuid           pin Nessus host after first match
- scan_schedules.scanner_type       wazuh|nessus, default wazuh for
                                    backwards compat
- Backfill: every existing vuln sources = ["wazuh"],
  first_detected_by = wazuh

Model helpers:
- Vulnerability.source_list / cross_confirmed / is_pseudo_cve properties
- Vulnerability.add_source(name) / remove_source(name) (no commit)
- Asset.nessus_host_uuid column
- ScanSchedule.scanner_type column

No behaviour change yet — Phase 2 will add the NessusClient + sync
function that actually populate these fields.
2026-05-13 23:04:01 +02:00
vulncheck 035f010d1b fix(auth): SQLEnum values_callable for AuthProvider — match lowercase DB values
Postgres authprovider enum was created (migration 009) with lowercase
values 'local','ldap','saml','oidc'. By default SQLAlchemy maps enum
columns by member NAME, which for AuthProvider are uppercase
(LOCAL/LDAP/...). On read, SQLAlchemy tried to find a member named
'local' and raised:

    LookupError: 'local' is not among the defined enum values.
    Possible values: LOCAL, LDAP, SAML, OIDC

Fix: pass values_callable=lambda x: [e.value for e in x] to the SQLEnum
column so SQLAlchemy compares against values, not names. No schema or
data change required.
2026-05-12 19:26:42 +02:00
vulncheck 25c8ef0866 feat(auth): multi-provider auth foundation (Strategy pattern + TOTP)
Phase 1 of the LDAPS / SAML 2.0 / OIDC integration. Lays the abstraction
so subsequent provider strategies (LDAP, OIDC, SAML) plug in without
re-wiring the login endpoint.

Backend changes:
- Alembic migration 008 adds users.auth_provider (enum: local/ldap/saml/oidc),
  external_id (indexed), external_groups (JSON), totp_secret, totp_enabled,
  last_provider_sync. password_hash becomes nullable for external users.
  Audit event enum extended with LOGIN_LDAP_SUCCESS, LOGIN_SSO_SUCCESS,
  AUTH_PROVIDER_FAILED, JIT_USER_CREATED, EXTERNAL_ROLE_MAPPED,
  USER_AUTO_LINKED, MFA_ENABLED/DISABLED/VERIFIED/FAILED.
- app/auth/strategies/ — Strategy Pattern: AuthStrategy ABC + ExternalIdentity
  portable identity + AuthResult. LocalAuthStrategy refactors existing
  bcrypt login. Constant-time dummy verify on user-not-found to defeat
  enumeration.
- app/auth/totp.py — RFC 6238 helpers (pyotp). Secret encrypted at rest
  with Fernet (key from AUTH_PROVIDER_CRYPTO_KEY env var). Never logged.
- app/auth/role_mapper.py — fnmatch-based external-groups -> UserRole
  mapping; rules in settings.auth_role_mappings JSON, admin-editable
  (Phase 5 UI to follow).
- app/auth/jit_provisioner.py — JIT user creation with auto-link by email
  on first SSO login (per requirements). Re-evaluates role on every login.
- app/auth/orchestrator.py — chains credential strategies in configurable
  AUTH_LOOKUP_ORDER. Generic safe message for every failure (audit logs
  the real reason).
- /auth/login refactored to use orchestrator. MFA gate: returns
  mfa_required=true + short-lived mfa_token if user has TOTP enabled;
  client POSTs /auth/mfa/verify with code to complete login.
- New endpoints: /auth/mfa/setup, /auth/mfa/activate, /auth/mfa/disable,
  /auth/providers (public — frontend uses to render correct buttons).
- requirements.txt: pyotp, cryptography, ldap3, authlib, itsdangerous,
  python3-saml, lxml.
- Dockerfile: libxml2-dev, libxmlsec1-dev, libxmlsec1-openssl, pkg-config
  for python3-saml; libsasl2/libldap/libssl-dev for future python-ldap.

Phase 2 (LDAPS), Phase 3 (OIDC), Phase 4 (SAML), Phase 5 (Admin UI for
provider config + role-mapping) will follow as separate commits.
2026-05-12 19:02:47 +02:00
vulncheck 356bf7b97f feat(risk-score): add ENISA EUVD enrichment + CPR score
EUVD (EU Vulnerability Database, ENISA) integration as second
authoritative catalog alongside CISA KEV. EU-Compliance use cases
benefit from a non-US source; CVEs confirmed by both catalogs get
the highest priority via score stacking.

Two ENISA endpoints are merged into one cached map (24h TTL):
- /exploitedvulnerabilities (analogous to CISA KEV)
- /criticalvulnerabilities (ENISA Critical flag)

Priority-Score formula:
- Exploit-Signal now triggered by KEV OR EUVD listing
- Catalog-Bonus stacking: KEV +10, EUVD +10, KEV-ransomware +5,
  EU-Critical +3. A CVE in both catalogs adds +20 base.

CPR Score (Cybersecurity Priority Risk = CVSS x EPSS x 10) added
as separate metric next to Priority, per JacquesKruger/EPSS-Server
convention. Calculated on-the-fly, no DB column needed.

New API filters: euvd_only, eu_critical, in_any_catalog,
in_both_catalogs. Setting toggle enrichment_euvd_enabled (default true).

Frontend: new EUVD column (blue badge, EU-CRIT sub-badge), CPR column
with mini-bar, four catalog filter checkboxes. Detail page splits
threat intel into CISA KEV / ENISA EUVD / EPSS sections; breakdown
shows EUVD bonus row and CPR score with both-catalogs hint.
2026-05-11 19:47:37 +02:00
vulncheck 42f867a58b feat(risk-score): enrich priority with EPSS + CISA KEV
Risk score now pulls from multiple threat intel sources instead of
only AI/CVSS data:

- EPSS (FIRST.org) — probability of exploitation in next 30 days
- CISA KEV — known actively exploited vulnerabilities (with ransomware flag)
- Existing Wazuh exploit flags as fallback

Adds DB columns (epss_score, epss_percentile, kev_listed, kev_*,
enrichment_sources, enrichment_updated_at), an enrichment_service
with cached KEV catalog (24h TTL in settings table) and batched
EPSS lookups, manual + bulk + KEV-refresh endpoints, automatic
enrichment after Wazuh sync, and a daily scheduler job to refresh
scores.

Frontend gets KEV badges, EPSS column with percentile, KEV-only +
EPSS-min filters, a "Refresh Threat Intel" button, and a priority
score breakdown card on the detail page.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 15:37:53 +02:00
vulncheck 6969d0c62e Initial release v1.0.0
VulnCheck - Open Source Vulnerability Management for Wazuh

Features:
- Vulnerability management with Wazuh integration
- AI-powered CVE analysis (OpenAI, Anthropic, Google, DeepSeek, Ollama, Infomaniak)
- SLA policy enforcement with automated email alerts
- Automated patch verification via Wazuh Syscollector
- Role-based access control (Admin, Editor, Readonly)
- PDF/CSV reporting for compliance workflows
- Full audit trail

https://gitea.isuit.ch/vulncheck/vulncheck
2026-02-08 10:15:20 +01:00