From 781ee3379a79e1af3593d82d075dfaab62e5b52f Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Tue, 24 Feb 2026 17:13:16 -0600 Subject: [PATCH 1/5] wip: opengraph pathfinding for users --- docs/analyze-data/explore/search.mdx | 10 +++++----- docs/opengraph/faq.mdx | 4 +--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/analyze-data/explore/search.mdx b/docs/analyze-data/explore/search.mdx index 77bf63bb..ed3b1985 100644 --- a/docs/analyze-data/explore/search.mdx +++ b/docs/analyze-data/explore/search.mdx @@ -25,8 +25,6 @@ The **Explore** page provides the following methods for searching for objects an -BloodHound currently supports the **Search** and **Cypher** search methods for OpenGraph data, with support for Pathfinding coming soon. - Which method you choose depends on your specific use case and what you're trying to accomplish. This page describes each of the search methods in more detail and provides guidance on when to use each one. You can interact with objects in the [graph](#graph-view) and customize the view to explore the data more effectively, regardless of which search method you use. @@ -67,9 +65,7 @@ group:admin ## Pathfinding -The **Pathfinding** tab allows you to discover relationships between objects by finding paths between them. This is particularly useful for investigating potential attack paths in an environment. - -BloodHound currently supports the **Search** and **Cypher** search methods for OpenGraph data, with support for Pathfinding coming soon. +The **Pathfinding** tab allows you to discover relationships between objects by finding paths between them. This is particularly useful for investigating potential attack paths in an environment or exploring how different objects are connected in specific OpenGraph data sources. Use cases for the pathfinding search method include: @@ -89,6 +85,10 @@ Pathfinding also includes options to customize your search: * **Filter edges** —Select which edge types to include in the results. By default, all edge types are selected; deselect any you don't want included in the paths to focus on relevant relationships. + + Filtering options are available for schema-based data only. If you're exploring schema-less OpenGraph data, edge filtering options are not available. + + ## Cypher The **Cypher** tab allows you to perform complex searches using Cypher queries. diff --git a/docs/opengraph/faq.mdx b/docs/opengraph/faq.mdx index 60b06091..10835cfb 100644 --- a/docs/opengraph/faq.mdx +++ b/docs/opengraph/faq.mdx @@ -31,9 +31,7 @@ You can remove generic data by using one of the following three (3) options: -**Search:** Yes! As of v8.5.0, OpenGraph nodes are partially supported in the search functionality on the **Explore** page. You can search for OpenGraph nodes by display name or object ID, and visualize them in the graph with custom icons and colors. However, you cannot yet prepend search queries by OpenGraph node types. - -**Pathfinding:** Not yet. OpenGraph edges are not currently supported in the **Pathfinding** tab on the **Explore** page. For pathfinding queries involving OpenGraph data, you must use the Cypher tab to query the data manually. +Yes! BloodHound supports custom nodes in **Search** and **Pathfinding**. However, prepending queries with custom node types is not yet supported. Have you built a cool project using OpenGraph and want it featured here? Already got your project in the list and need to update something? Open a ["Library Change" issue](https://github.com/SpecterOps/bloodhound-docs/issues) on the BloodHound Docs repo and we'll get it added for you! From 5e1e9cdf721d3ecfbc610ccf5d669ff7fa9eeae0 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Wed, 25 Feb 2026 11:19:10 -0600 Subject: [PATCH 2/5] wip: opengraph pathfinding for developers --- docs/analyze-data/explore/search.mdx | 2 +- docs/opengraph/schema.mdx | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/analyze-data/explore/search.mdx b/docs/analyze-data/explore/search.mdx index ed3b1985..ed750fa9 100644 --- a/docs/analyze-data/explore/search.mdx +++ b/docs/analyze-data/explore/search.mdx @@ -86,7 +86,7 @@ Pathfinding also includes options to customize your search: * **Filter edges** —Select which edge types to include in the results. By default, all edge types are selected; deselect any you don't want included in the paths to focus on relevant relationships. - Filtering options are available for schema-based data only. If you're exploring schema-less OpenGraph data, edge filtering options are not available. + Filtering options are available for [schema-based data](/opengraph/schema) only. If you're exploring generic (schema-less) OpenGraph data, edge filtering options are not available. ## Cypher diff --git a/docs/opengraph/schema.mdx b/docs/opengraph/schema.mdx index 534ccdbb..89b2ef6a 100644 --- a/docs/opengraph/schema.mdx +++ b/docs/opengraph/schema.mdx @@ -6,11 +6,16 @@ description: "Description of the OpenGraph JSON Schema" Applies to BloodHound Enterprise and CE -# Schema +This page explains the JSON format BloodHound ingests to display OpenGraph nodes and edges. -In this section, you will find all the information to create a JSON file that BloodHound can ingest and use to display your Nodes and Edges. +Terms used on this page: -The most up-to-date JSON Schema can always be found in our CE repository. Currently, the location of the node and edge schema files in our source code can be found [here](https://github.com/SpecterOps/BloodHound/tree/main/cmd/api/src/services/upload/jsonschema). +- **Schema-less (generic) data** refers to OpenGraph payloads that follow the minimum node and edge JSON format. +- **Schema-based data** refers to OpenGraph payloads that follow an extension-defined schema (separate from the payload). + +This page focuses on the JSON requirements for generic data. + +You can find the latest node and edge schemas in the BloodHound [source code](https://github.com/SpecterOps/BloodHound/tree/main/cmd/api/src/services/upload/jsonschema) on GitHub. # Ingesting Generic Formatted Data @@ -39,9 +44,15 @@ At minimum, your JSON file should have these elements: The `nodes` and `edges` must conform to our JSON Schema, see details below. The validation of the data occurs at upload time. -When ingest completes, the generic data will be available via **Cypher search ONLY**. Generic data is not searchable via the pathfinding feature (yet). +When ingest completes, generic data is available through all [Explore](/analyze-data/explore/search) options: + +- **Search** +- **Pathfinding** +- **Cypher** + +In **Pathfinding**, edge filtering options are available for schema-based data only. For generic data, edge filtering options are not available. -**Entity Panels**: clicking on a generic node or edge will only render the entity’s property bag. At this time there is no support for defining entity panels for generic entities. +**Entity Panels**: clicking on a generic node or edge will only render the entity's property bag. At this time there is no support for defining entity panels for generic entities. ## Nodes From e6d0c59f4e3382227249148d02dbecb98c07cc9c Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Wed, 25 Feb 2026 11:28:10 -0600 Subject: [PATCH 3/5] wip: disambiguate payload format and schema requirements --- docs/opengraph/schema.mdx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/opengraph/schema.mdx b/docs/opengraph/schema.mdx index 89b2ef6a..0e6db392 100644 --- a/docs/opengraph/schema.mdx +++ b/docs/opengraph/schema.mdx @@ -6,18 +6,18 @@ description: "Description of the OpenGraph JSON Schema" Applies to BloodHound Enterprise and CE -This page explains the JSON format BloodHound ingests to display OpenGraph nodes and edges. +This page explains the JSON payload structure and minimum JSON schema requirements that BloodHound uses to ingest OpenGraph nodes and edges. Terms used on this page: -- **Schema-less (generic) data** refers to OpenGraph payloads that follow the minimum node and edge JSON format. -- **Schema-based data** refers to OpenGraph payloads that follow an extension-defined schema (separate from the payload). +- **Schema-less (generic) data** refers to OpenGraph payloads that follow the minimum node and edge JSON schemas on this page. +- **Schema-based data** refers to OpenGraph payloads that use an extension-defined schema outside the payload itself. This page focuses on the JSON requirements for generic data. You can find the latest node and edge schemas in the BloodHound [source code](https://github.com/SpecterOps/BloodHound/tree/main/cmd/api/src/services/upload/jsonschema) on GitHub. -# Ingesting Generic Formatted Data +# Ingesting Schema-less (Generic) Data ## File Requirements @@ -27,9 +27,9 @@ You can mix file types in a single upload (e.g. Sharphound + Generic). Compressed ZIPs containing multiple file types are supported. -## JSON Format +## JSON Payload Structure -The standard BloodHound UI upload screen now accepts files in a generic format. You can continue using it as before. +The standard BloodHound UI upload screen accepts schema-less (generic) OpenGraph payloads. You can continue using it as before. At minimum, your JSON file should have these elements: @@ -42,7 +42,7 @@ At minimum, your JSON file should have these elements: } ``` -The `nodes` and `edges` must conform to our JSON Schema, see details below. The validation of the data occurs at upload time. +The `nodes` and `edges` must conform to the minimum JSON schemas (see details below). BloodHound validates that the JSON is well-formed and that nodes and edges meet these schema requirements, but it does not enforce additional structure or constraints beyond them. When ingest completes, generic data is available through all [Explore](/analyze-data/explore/search) options: From fb361cfb6e67d9b6f53b5bb6d91a3ccf0c643c00 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Wed, 25 Feb 2026 11:44:41 -0600 Subject: [PATCH 4/5] fix: heading levels --- docs/opengraph/schema.mdx | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/opengraph/schema.mdx b/docs/opengraph/schema.mdx index 0e6db392..d14be7d3 100644 --- a/docs/opengraph/schema.mdx +++ b/docs/opengraph/schema.mdx @@ -17,9 +17,9 @@ This page focuses on the JSON requirements for generic data. You can find the latest node and edge schemas in the BloodHound [source code](https://github.com/SpecterOps/BloodHound/tree/main/cmd/api/src/services/upload/jsonschema) on GitHub. -# Ingesting Schema-less (Generic) Data +## Ingesting Schema-less (Generic) Data -## File Requirements +### File Requirements Acceptable formats: `.json`, `.zip` @@ -27,7 +27,7 @@ You can mix file types in a single upload (e.g. Sharphound + Generic). Compressed ZIPs containing multiple file types are supported. -## JSON Payload Structure +### JSON Payload Structure The standard BloodHound UI upload screen accepts schema-less (generic) OpenGraph payloads. You can continue using it as before. @@ -55,9 +55,9 @@ When ingest completes, generic data is available through all [Explore](/analyze- **Entity Panels**: clicking on a generic node or edge will only render the entity's property bag. At this time there is no support for defining entity panels for generic entities. -## Nodes +### Nodes -### Property Rules +#### Property Rules Properties must be primitive types or arrays of primitive types @@ -67,7 +67,7 @@ Arrays must be homogeneous (e.g. all strings or all numbers) An array of kind labels for the node. The first element is treated as the node's primary kind and is used to determine which icon to display in the graph UI. This primary kind is only used for visual representation and has no semantic significance for data processing. -### Node JSON +#### Node JSON The following is the JSON schema that all nodes must conform to. @@ -123,7 +123,7 @@ The following is the JS } ``` -## Edges +### Edges Edges names cannot contain dash `-`. It is highly recommended to use Pascal Case and no special characters. @@ -131,7 +131,7 @@ From [tuple.nl](https://www.tuple.nl/en/knowledge-base/pascal-case): Pascal Case See Neo4j [Naming and Conventions](https://neo4j.com/docs/cypher-manual/current/syntax/naming/) for more details. -### Edge JSON +#### Edge JSON The following is the JSON schema that all edges must conform to. @@ -258,7 +258,7 @@ The following is the JS } ``` -### Post-processing +#### Post-processing Post-processing in BloodHound refers to the analysis phase where the system creates certain edges after ingesting data to identify attack paths. @@ -349,7 +349,7 @@ See the following example OpenGraph payload that produces the effect: } ``` -## Optional Metadata Field +### Optional Metadata Field You can optionally include a metadata object at the top level of your JSON payload. This metadata currently supports a single field: @@ -371,7 +371,7 @@ Example: If present, the `source_kind` will be added to the `kinds` list of all nodes in the file during ingest. This feature is optional. -## Minimal Working JSON +### Minimal Working JSON The following is a minimal example payload that conforms to the node and edge schemas above. You can use this as a starting point to build your own OpenGraph. Copy and paste the following example into a new `.json` file or download this example file. From 9d0413d56428a975f02aa6340a0f21ff3f8c79e1 Mon Sep 17 00:00:00 2001 From: Jeff Matthews Date: Fri, 27 Feb 2026 09:10:05 -0600 Subject: [PATCH 5/5] docs: apply suggestions from review --- docs/analyze-data/explore/search.mdx | 12 ++++---- docs/opengraph/faq.mdx | 2 +- docs/opengraph/schema.mdx | 42 +++++++++++++--------------- 3 files changed, 26 insertions(+), 30 deletions(-) diff --git a/docs/analyze-data/explore/search.mdx b/docs/analyze-data/explore/search.mdx index ed750fa9..bb6ce878 100644 --- a/docs/analyze-data/explore/search.mdx +++ b/docs/analyze-data/explore/search.mdx @@ -7,7 +7,9 @@ description: Search for objects and visualize relationships between them in the After [uploading data](/get-started/quickstart/community-edition-quickstart#get-data-into-bloodhound) to BloodHound, use the **Explore** page to search for objects and visualize their relationships. The graph displays nodes and edges, helping you understand your environment and identify potential attack paths. -BloodHound supports multiple data sources, including Active Directory, Azure (Entra ID), and other identity services through [OpenGraph](/opengraph/overview). The search methods return results for all data sources. +BloodHound supports multiple data sources, including Active Directory, Azure (Entra ID), and other identity services through [OpenGraph](/opengraph/overview). + +BloodHound supports all search methods for [_schema-based_](/opengraph/schema) OpenGraph data. If you're exploring _schema-less_ OpenGraph data, you can use the **Search** and **Cypher** search methods only. The **Explore** page provides the following methods for searching for objects and visualizing their relationships: @@ -65,7 +67,9 @@ group:admin ## Pathfinding -The **Pathfinding** tab allows you to discover relationships between objects by finding paths between them. This is particularly useful for investigating potential attack paths in an environment or exploring how different objects are connected in specific OpenGraph data sources. +The **Pathfinding** tab allows you to discover relationships between objects by finding paths between them. This is particularly useful for investigating potential attack paths across identity providers and cloud services in a single graph view. + +Pathfinding is available for [schema-based](/opengraph/schema) OpenGraph data only. Use cases for the pathfinding search method include: @@ -85,10 +89,6 @@ Pathfinding also includes options to customize your search: * **Filter edges** —Select which edge types to include in the results. By default, all edge types are selected; deselect any you don't want included in the paths to focus on relevant relationships. - - Filtering options are available for [schema-based data](/opengraph/schema) only. If you're exploring generic (schema-less) OpenGraph data, edge filtering options are not available. - - ## Cypher The **Cypher** tab allows you to perform complex searches using Cypher queries. diff --git a/docs/opengraph/faq.mdx b/docs/opengraph/faq.mdx index 10835cfb..ae5752dc 100644 --- a/docs/opengraph/faq.mdx +++ b/docs/opengraph/faq.mdx @@ -31,7 +31,7 @@ You can remove generic data by using one of the following three (3) options: -Yes! BloodHound supports custom nodes in **Search** and **Pathfinding**. However, prepending queries with custom node types is not yet supported. +Yes! BloodHound supports **Search** and **Pathfinding** for [_schema-based_](/opengraph/schema) OpenGraph data. For _schema-less_ OpenGraph data, only **Search** and **Cypher** are supported. Custom node type prefixes in queries are not yet supported. Have you built a cool project using OpenGraph and want it featured here? Already got your project in the list and need to update something? Open a ["Library Change" issue](https://github.com/SpecterOps/bloodhound-docs/issues) on the BloodHound Docs repo and we'll get it added for you! diff --git a/docs/opengraph/schema.mdx b/docs/opengraph/schema.mdx index d14be7d3..66d9a4ff 100644 --- a/docs/opengraph/schema.mdx +++ b/docs/opengraph/schema.mdx @@ -10,10 +10,10 @@ This page explains the JSON payload structure and minimum JSON schema requiremen Terms used on this page: -- **Schema-less (generic) data** refers to OpenGraph payloads that follow the minimum node and edge JSON schemas on this page. +- **Schema-less (generic) data** refers to OpenGraph payloads that follow the minimum node and edge schemas described on this page. - **Schema-based data** refers to OpenGraph payloads that use an extension-defined schema outside the payload itself. -This page focuses on the JSON requirements for generic data. +This page focuses on the JSON requirements for schema-less (generic) data. You can find the latest node and edge schemas in the BloodHound [source code](https://github.com/SpecterOps/BloodHound/tree/main/cmd/api/src/services/upload/jsonschema) on GitHub. @@ -27,9 +27,9 @@ You can mix file types in a single upload (e.g. Sharphound + Generic). Compressed ZIPs containing multiple file types are supported. -### JSON Payload Structure +### Data Payload Structure -The standard BloodHound UI upload screen accepts schema-less (generic) OpenGraph payloads. You can continue using it as before. +The standard BloodHound UI upload screen accepts all OpenGraph payloads—both schema-less (generic) and schema-based. At minimum, your JSON file should have these elements: @@ -44,28 +44,24 @@ At minimum, your JSON file should have these elements: The `nodes` and `edges` must conform to the minimum JSON schemas (see details below). BloodHound validates that the JSON is well-formed and that nodes and edges meet these schema requirements, but it does not enforce additional structure or constraints beyond them. -When ingest completes, generic data is available through all [Explore](/analyze-data/explore/search) options: +When ingest completes, you can [search](/analyze-data/explore/search) OpenGraph data. Supported search methods depend on whether the data is schema-based or schema-less: -- **Search** -- **Pathfinding** -- **Cypher** - -In **Pathfinding**, edge filtering options are available for schema-based data only. For generic data, edge filtering options are not available. - -**Entity Panels**: clicking on a generic node or edge will only render the entity's property bag. At this time there is no support for defining entity panels for generic entities. +| Search method | Schema-based | Schema-less | +| --- | --- | --- | +| Node Search | | | +| Pathfinding | | | +| Cypher | | | +**Entity Panels**: clicking on a node or edge will only render the entity's property bag. At this time there is no support for defining entity panels for generic entities. ### Nodes #### Property Rules -Properties must be primitive types or arrays of primitive types - -Nested objects and arrays of objects are not allowed - -Arrays must be homogeneous (e.g. all strings or all numbers) - -An array of kind labels for the node. The first element is treated as the node's primary kind and is used to determine which icon to display in the graph UI. This primary kind is only used for visual representation and has no semantic significance for data processing. +- Properties must be primitive types or arrays of primitive types. +- Nested objects and arrays of objects are not allowed. +- Arrays must be homogeneous (for example, all strings or all numbers). +- An array of kind labels for the node. The first element is treated as the node's primary kind and determines which icon appears in the graph UI. This primary kind is only used for visual representation and has no semantic significance for data processing. #### Node JSON @@ -260,9 +256,9 @@ The following is the JS #### Post-processing -Post-processing in BloodHound refers to the analysis phase where the system creates certain edges after ingesting data to identify attack paths. +Post-processing in BloodHound refers to a series of steps during analysis phase where the system creates specific edges after ingesting data to enrich the graph and more accurately reflect the graph's state. -After ingesting data, BloodHound analyzes the graph state and adds edges it considers useful. BloodHound regenerates "post-processed" edges after it builds a complete graph. Before regenerating post-processed edges, BloodHound deletes any existing ones. As a result, BloodHound removes any post-processed edges that you add directly to an OpenGraph payload. +After ingesting data, BloodHound analyzes the graph state and adds edges that are essential to accurately represent the environment and support attack path analysis. BloodHound regenerates "post-processed" edges after it builds a complete graph. Before regenerating post-processed edges, BloodHound deletes any existing ones. As a result, BloodHound removes any post-processed edges that you add directly to an OpenGraph payload. BloodHound creates the following edges during post-processing: @@ -351,7 +347,7 @@ See the following example OpenGraph payload that produces the effect: ### Optional Metadata Field -You can optionally include a metadata object at the top level of your JSON payload. This metadata currently supports a single field: +You can optionally include a metadata object at the top level of your data payload. This metadata currently supports a single field: - `source_kind`: a string that applies to all nodes in the file, used to attribute a source to ingested nodes (e.g. Github, Snowflake, MSSQL). This is useful for tracking where a node originated. We internally use this concept already for AD/Azure, using the labels “Base” and “AZBase” respectively. @@ -371,7 +367,7 @@ Example: If present, the `source_kind` will be added to the `kinds` list of all nodes in the file during ingest. This feature is optional. -### Minimal Working JSON +### Minimal Viable Data Payload The following is a minimal example payload that conforms to the node and edge schemas above. You can use this as a starting point to build your own OpenGraph. Copy and paste the following example into a new `.json` file or download this example file.