> your AI agent picks dependencies from memory; give it dated facts — try starlog.dev ↗ vet your agent's deps ↗ vibe-coding is fine. vibe-importing isn’t. — try starlog.dev ↗ vibe-importing isn’t fine ↗ your agent has never seen your private packages — try starlog.dev ↗ facts for private packages ↗ a linter for the dependencies your AI agent picks — try starlog.dev ↗ a linter for agent deps ↗ whois is redacted, cdns mask the rest — get the real operator — try whoisgeni.us ↗ who really runs that domain ↗ domain attribution that shows its work — full evidence chain — try whoisgeni.us ↗ domain intel w/ evidence ↗

← Back to Articles

Flowsint: Building a Graph-Based OSINT Platform That Doesn't Choke on Async Enrichment

[ View on GitHub ]

Flowsint: Building a Graph-Based OSINT Platform That Doesn't Choke on Async Enrichment

Hook

Most OSINT tools fail the moment you pivot from one domain to 500 subdomains—HTTP timeouts kill the request before enrichment finishes. Flowsint decouples investigation from execution using Celery workers, turning hours-long scans into background jobs that actually complete.

Context

Security researchers and journalists conducting open-source intelligence investigations face a brutal choice: pay $3,000+ annually for Maltego Enterprise with its proprietary transform ecosystem, or wrangle SpiderFoot's 200+ modules that break with API changes and run synchronously until your browser times out. Tools like Recon-ng excel at scripted reconnaissance but lack visual graph exploration. Hunchly provides timeline management for manual investigations but no automation. The common thread? Either you get visual investigation with vendor lock-in, or you get extensibility with architectural limitations that make long-running enrichment pipelines a nightmare.

Flowsint emerged in 2024 as an MIT-licensed answer to this problem. It treats OSINT investigations as graph problems—entities connected by relationships—and implements enrichment as asynchronous Celery tasks that write to Neo4j. The promise is Maltego's visual investigation model without the licensing costs, plus SpiderFoot's extensibility without the monolithic architecture that makes adding enrichers fragile. With 8,977 stars and active development, it's attracting teams who need custom OSINT workflows but can't justify enterprise tool costs or don't want to maintain brittle Python scripts.

Technical Insight

Flowsint's architecture solves the async enrichment problem through deliberate separation of concerns. The React/TypeScript frontend makes API calls to a FastAPI backend, which immediately returns and spawns Celery tasks via Redis. These tasks execute enrichers—Python modules that inherit from base classes—in worker processes. Results write to both Neo4j (graph relationships) and PostgreSQL (structured metadata). This means a domain enrichment that spawns 500 subdomain lookups doesn't block the HTTP request; users see nodes populate in real-time as workers complete.

The enricher plugin model is where Flowsint differentiates itself. Here's what a custom enricher looks like:

from flowsint_core.enrichers import BaseEnricher
from flowsint_types import Domain, IPAddress
from pydantic import BaseModel

class DNSResolverInput(BaseModel):
    domain: Domain

class DNSResolverOutput(BaseModel):
    ip_addresses: list[IPAddress]

class DNSResolverEnricher(BaseEnricher):
    name = "dns_resolver"
    input_model = DNSResolverInput
    output_model = DNSResolverOutput
    
    async def enrich(self, input_data: DNSResolverInput) -> DNSResolverOutput:
        # Your resolution logic here
        ips = await resolve_dns(input_data.domain)
        
        # Write relationships to Neo4j
        for ip in ips:
            self.graph.create_relationship(
                input_data.domain,
                ip,
                relationship_type="RESOLVES_TO"
            )
        
        return DNSResolverOutput(ip_addresses=ips)

The Pydantic-based type system means FastAPI automatically validates inputs and generates OpenAPI documentation. The flowsint-types package defines entity schemas (Domain, IPAddress, EmailAddress, etc.) that enrichers consume and produce. Adding cryptocurrency wallet tracking or new entity types doesn't require core changes—you extend the type system and write enrichers that reference those types. This is the architectural win over Maltego, where custom entity types require transform SDK integration and aren't truly first-class.

The vault component addresses a real operational problem: storing API keys for third-party services (Shodan, VirusTotal, etc.) without leaking them in logs or database dumps. Flowsint implements envelope encryption using a master key derivation scheme. The code references MASTER_VAULT_KEY_V1, suggesting key versioning for rotation. When an enricher needs credentials, it requests them from the vault service, which decrypts at runtime. This beats SpiderFoot's approach of storing API keys in plaintext configuration files.

Nginx configuration reveals sophisticated security thinking. The default nginx.conf implements Host header allowlisting restricted to localhost, mitigating DNS rebinding attacks against single-user installs. If you're exposing Flowsint on a LAN or public IP, you must explicitly add your hostname to the allowlist. This forces operators to acknowledge they're exposing the service rather than accidentally opening it to attackers who can craft malicious DNS entries pointing to your internal IP. Most self-hosted OSINT tools ignore this attack vector entirely.

The frontend's claim of handling thousands of nodes without lag suggests WebGL canvas rendering or aggressive virtualization rather than DOM-based libraries. Traditional graph libraries like vis.js or cytoscape.js render every node as a DOM element, which becomes unusable above ~500 nodes. A canvas-based approach renders to a single element, maintaining 60fps even with complex graphs. This architectural choice makes Flowsint viable for large-scale investigations where a single domain pivot generates thousands of related entities.

Gotcha

The enricher architecture has a glaring omission: no built-in rate limiting or quota management. If you configure a Shodan enricher and run it against 1,000 domains, Celery workers will spawn concurrent tasks that hammer Shodan's API until you exhaust your credits or get banned. Maltego provides per-transform throttling configuration. SpiderFoot has module-level rate limiting. Flowsint gives you neither, meaning you'll implement semaphores or rate limiters in every enricher that touches a paid API. For a platform targeting cybersecurity analysts who regularly work with quota-constrained services, this is a surprising gap.

Authentication and multi-user support are bare-bones. The system uses username/password authentication without SSO, LDAP, or SAML support. There's no documented session management, concurrent login handling, or API token system for programmatic access. If you're deploying this for a security team, you'll struggle with user management. The lack of audit logging means you can't track who ran which enrichers or accessed sensitive investigation data—a non-starter for compliance-heavy organizations.

Backup and disaster recovery are undocumented. Neo4j stores your entire investigation graph, and the vault holds encrypted API keys, but there's no tooling or guidance for backup procedures. The MASTER_VAULT_KEY_V1 naming suggests key rotation might be planned, but it's unclear if rotating the master key is actually implemented or will brick your existing vault entries. For a tool designed for long-running investigations that might span months, the lack of operational documentation around data durability is concerning.

Verdict

Use if: You're building custom OSINT workflows that require long-running enrichment pipelines and you can't justify Maltego Enterprise licensing costs. The Celery-backed async architecture genuinely solves the timeout problems that plague synchronous tools, and the plugin model makes adding domain-specific enrichers straightforward. The MIT license and TypeScript frontend make this a strong foundation if you have Python developers who can build enrichers and operational guardrails around rate limiting and backups. Skip if: You need enterprise features like SSO, audit logging, or multi-tenancy—this is a single-team tool at best. Also skip if you want batteries-included OSINT coverage; SpiderFoot's 200+ modules beat Flowsint's starter set, and you'll spend time building enrichers rather than investigating. If you already have a Maltego license and invested in custom transforms, the migration cost outweighs Flowsint's benefits. Finally, skip if you lack Python expertise to implement rate limiting, backup procedures, and enricher error handling—the architectural foundation is solid but operationally incomplete.