Skip to content

Deleting a sketch leaves its entire graph in Neo4j #230

Description

@jameshenning

Summary

DELETE /api/sketches/{id} returns 204 and removes the sketch from Postgres, but every Neo4j node carrying that sketch_id is left in place. The graph data of a "deleted" sketch survives indefinitely, invisible to the UI but fully present in the database.

Version

v1.2.12 (docker-compose.prod.yml, ghcr.io/reconurge/flowsint-api:1.2.12)

Reproduction

  1. Create an investigation and a sketch.

  2. Add a domain node and run an enricher that expands the graph. domain_to_subdomains on a domain with many subdomains makes the effect obvious — in my run it produced 22,248 subdomain nodes.

  3. Confirm the graph: GET /api/sketches/{sketch_id}/graph → 22,254 nodes.

  4. DELETE /api/sketches/{sketch_id} → 204 No Content.

  5. Query Neo4j directly:

    MATCH (n) WHERE n.sketch_id IS NOT NULL RETURN count(n);

    → 22254

Every node is still there, still tagged with the deleted sketch's id. The same holds for a small sketch — I first saw it with a 3-node sketch, where the delete left all 3.

Expected

Deleting a sketch should delete the graph belonging to it, or the API should document that it does not and offer a way to purge. At present the only route is manual:

MATCH (n {sketch_id:'<id>'}) WITH n LIMIT 5000 DETACH DELETE n RETURN count(n);

(repeated until it returns 0 — a single unbatched DETACH DELETE on a large sketch is heavy).

Impact

Two concerns:

  1. Data retention. The docs describe Flowsint as local and privacy-first, which invites the reading that deleting an investigation disposes of its data. It does not. For anyone handling subject data under a retention policy, "delete" not deleting is a meaningful gap.
  2. Unbounded growth. Nothing reclaims these nodes, so a Neo4j instance accumulates the full graph of every sketch ever deleted. Subdomain enumeration produces tens of thousands of nodes per run, so this adds up quickly.

Note

Deleting the owning investigation (DELETE /api/investigations/{id}, also 204) does not clean them up either.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions