[PR #154] feat(enrichers): add ip_to_security_risk — Shodan-backed weighted risk scoring for IP nodes #2624

Open
opened 2026-06-07 15:05:08 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/reconurge/flowsint/pull/154
Author: @adityaa206
Created: 6/2/2026
Status: 🔄 Open

Base: mainHead: feat/ip-security-risk-enricher


📝 Commits (3)

  • 21e7c31 feat(enrichers): add ip_to_security_risk enricher via Shodan
  • 4712bac test(enrichers): add comprehensive test suite for ip_to_security_risk
  • 5e28915 fix(enrichers): replace CVSS floor hack with real NVD API v2 lookup

📊 Changes

3 files changed (+1702 additions, -0 deletions)

View changed files

📝 flowsint-enrichers/pyproject.toml (+1 -0)
flowsint-enrichers/src/flowsint_enrichers/ip/to_security_risk.py (+627 -0)
flowsint-enrichers/tests/enrichers/test_ip_to_security_risk.py (+1074 -0)

📄 Description

Summary

  • Adds a new ip_to_security_risk enricher under flowsint-enrichers/src/flowsint_enrichers/ip/to_security_risk.py
  • Takes an Ip node → queries Shodan → emits a RiskProfile node + Port nodes, all linked in the graph
  • Adds shodan>=1.31,<2.0 to flowsint-enrichers dependencies

What problem does this solve?

Flowsint already excels at mapping entity relationships (domains, IPs, social accounts, etc.), but it has no native way to score the security danger of an IP node. An investigator looking at an IP in the graph has no immediate signal of how risky it is.

This enricher fills that gap: it enriches an IP with a 0–100 risk score, a critical / high / medium / low classification, CVE IDs, exposure-surface summary, compliance risk flags, and mitigation recommendations — all surfaced as a RiskProfile node linked directly to the IP.

Scoring model

Adapted from RedFlag, an open-source M&A cybersecurity due-diligence tool, the formula combines four weighted factors:

score = (cvss_norm × 0.35)        ← how severe are the CVEs?
      + (exposure  × 0.25)        ← is this internet-facing?
      + (sensitivity × 0.25)      ← data classification (always UNKNOWN — no asset inventory)
      + (exploit   × 0.15)        ← are CVEs weaponised?
      × evidence_multiplier        ← how confident is the data?
Factor Value Score
Exposure Internet-facing (HTTP/SSH/RDP/DB ports) 100
Exposure Unknown 50
Exploit status Public CVE linked by Shodan 65
Exploit status No CVE data 30
Evidence CORRELATED — CVEs + port confirmed ×0.95
Evidence INFERRED — host found, no CVEs ×0.85

Risk level bands: critical ≥ 75 · high ≥ 50 · medium ≥ 25 · low < 25

Graph output

(Ip) -[HAS_RISK_PROFILE]-> (RiskProfile)
(Ip) -[HAS_PORT]->         (Port)          ← one per open Shodan port

The RiskProfile node carries:

  • overall_risk_score (0–100), risk_level, assessment_date
  • vulnerabilities (CVE IDs), risk_factors, attack_vectors
  • exposure_surface (org, ASN, hostnames, open ports)
  • compliance_risks (PCI-DSS / GDPR / ISO 27001 flags)
  • mitigation_strategies, confidence, source = "Shodan"

Required vault secret

Key Where to get it
SHODAN_API_KEY https://account.shodan.io — 1 credit per api.host() call

Test plan

  • Add SHODAN_API_KEY to Flowsint vault
  • Open any Ip node in the investigation graph
  • Run enricher ip_to_security_risk on it
  • Verify RiskProfile node appears linked via HAS_RISK_PROFILE
  • Verify Port nodes appear linked via HAS_PORT
  • Confirm score and risk level are plausible for the IP under test
  • Confirm a Shodan-rate-limited or invalid key returns a graceful log warning, not a crash

Files changed

File Change
flowsint-enrichers/src/flowsint_enrichers/ip/to_security_risk.py New — full enricher implementation
flowsint-enrichers/pyproject.toml Added shodan>=1.31,<2.0 dependency

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/reconurge/flowsint/pull/154 **Author:** [@adityaa206](https://github.com/adityaa206) **Created:** 6/2/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/ip-security-risk-enricher` --- ### 📝 Commits (3) - [`21e7c31`](https://github.com/reconurge/flowsint/commit/21e7c314ec51a9e970d9a6114ae6f3842bbde33f) feat(enrichers): add ip_to_security_risk enricher via Shodan - [`4712bac`](https://github.com/reconurge/flowsint/commit/4712bac363b7355c0be61cff9ba33d80b4c7314e) test(enrichers): add comprehensive test suite for ip_to_security_risk - [`5e28915`](https://github.com/reconurge/flowsint/commit/5e28915fb58cbf613004071dbe70c29bfea977f9) fix(enrichers): replace CVSS floor hack with real NVD API v2 lookup ### 📊 Changes **3 files changed** (+1702 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `flowsint-enrichers/pyproject.toml` (+1 -0) ➕ `flowsint-enrichers/src/flowsint_enrichers/ip/to_security_risk.py` (+627 -0) ➕ `flowsint-enrichers/tests/enrichers/test_ip_to_security_risk.py` (+1074 -0) </details> ### 📄 Description ## Summary - Adds a new **`ip_to_security_risk`** enricher under `flowsint-enrichers/src/flowsint_enrichers/ip/to_security_risk.py` - Takes an `Ip` node → queries Shodan → emits a `RiskProfile` node + `Port` nodes, all linked in the graph - Adds `shodan>=1.31,<2.0` to `flowsint-enrichers` dependencies ## What problem does this solve? Flowsint already excels at mapping entity relationships (domains, IPs, social accounts, etc.), but it has no native way to **score the security danger** of an IP node. An investigator looking at an IP in the graph has no immediate signal of how risky it is. This enricher fills that gap: it enriches an IP with a **0–100 risk score**, a **critical / high / medium / low** classification, CVE IDs, exposure-surface summary, compliance risk flags, and mitigation recommendations — all surfaced as a `RiskProfile` node linked directly to the IP. ## Scoring model Adapted from **RedFlag**, an open-source M&A cybersecurity due-diligence tool, the formula combines four weighted factors: ``` score = (cvss_norm × 0.35) ← how severe are the CVEs? + (exposure × 0.25) ← is this internet-facing? + (sensitivity × 0.25) ← data classification (always UNKNOWN — no asset inventory) + (exploit × 0.15) ← are CVEs weaponised? × evidence_multiplier ← how confident is the data? ``` | Factor | Value | Score | |--------|-------|-------| | Exposure | Internet-facing (HTTP/SSH/RDP/DB ports) | 100 | | Exposure | Unknown | 50 | | Exploit status | Public CVE linked by Shodan | 65 | | Exploit status | No CVE data | 30 | | Evidence | CORRELATED — CVEs + port confirmed | ×0.95 | | Evidence | INFERRED — host found, no CVEs | ×0.85 | Risk level bands: **critical** ≥ 75 · **high** ≥ 50 · **medium** ≥ 25 · **low** < 25 ## Graph output ``` (Ip) -[HAS_RISK_PROFILE]-> (RiskProfile) (Ip) -[HAS_PORT]-> (Port) ← one per open Shodan port ``` The `RiskProfile` node carries: - `overall_risk_score` (0–100), `risk_level`, `assessment_date` - `vulnerabilities` (CVE IDs), `risk_factors`, `attack_vectors` - `exposure_surface` (org, ASN, hostnames, open ports) - `compliance_risks` (PCI-DSS / GDPR / ISO 27001 flags) - `mitigation_strategies`, `confidence`, `source = "Shodan"` ## Required vault secret | Key | Where to get it | |-----|----------------| | `SHODAN_API_KEY` | https://account.shodan.io — 1 credit per `api.host()` call | ## Test plan - [x] Add `SHODAN_API_KEY` to Flowsint vault - [x] Open any `Ip` node in the investigation graph - [x] Run enricher `ip_to_security_risk` on it - [x] Verify `RiskProfile` node appears linked via `HAS_RISK_PROFILE` - [x] Verify `Port` nodes appear linked via `HAS_PORT` - [x] Confirm score and risk level are plausible for the IP under test - [x] Confirm a Shodan-rate-limited or invalid key returns a graceful log warning, not a crash ## Files changed | File | Change | |------|--------| | `flowsint-enrichers/src/flowsint_enrichers/ip/to_security_risk.py` | **New** — full enricher implementation | | `flowsint-enrichers/pyproject.toml` | Added `shodan>=1.31,<2.0` dependency | --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-06-07 15:05:08 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/flowsint#2624