- 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.
Ingesting Schema-less (Generic) Data
File Requirements
Acceptable formats:.json, .zip
You can mix file types in a single upload (e.g. Sharphound + Generic).
Compressed ZIPs containing multiple file types are supported.
Data Payload Structure
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: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, you can search OpenGraph data. Supported search methods depend on whether the data is schema-based or schema-less:
| Search method | Schema-based | Schema-less |
|---|---|---|
| Node Search | ||
| Pathfinding | ||
| Cypher |
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 (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
The following is the JSON schema that all nodes must conform to.Edges
Edges names cannot contain dash-. It is highly recommended to use Pascal Case and no special characters.
From tuple.nl: Pascal Case is a naming convention used in programming where compound words are written without spaces, and each word starts with an uppercase letter. It is commonly used for naming variables, functions, classes, and other identifiers in code. Pascal Case helps create descriptive and easily distinguishable names, contributing to the clarity of your code.
See Neo4j Naming and Conventions for more details.
Edge JSON
The following is the JSON schema that all edges must conform to.Post-processing
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 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.Show post-processed edges
Show post-processed edges
BloodHound creates the following edges during post-processing:
ADCSESC1ADCSESC3ADCSESC4ADCSESC6aADCSESC6bADCSESC9aADCSESC9bADCSESC10aADCSESC10bADCSESC13AddMemberAdminToAZAddOwnerAZMGAddMemberAZMGAddOwnerAZMGAddSecretAZMGGrantAppRolesAZMGGrantRoleAZRoleApproverCanPSRemoteCanRDPCoerceAndRelayNTLMToADCSCoerceAndRelayNTLMToLDAPCoerceAndRelayNTLMToLDAPSCoerceAndRelayNTLMToSMBDCSyncEnrollOnBehalfOfEnterpriseCAForExecuteDCOMExtendedByPolicyGoldenCertHasTrustKeysIssuedSignedByOwnsOwnsLimitedRightsProtectAdminGroupsSyncLAPSPasswordSyncedToADUserSyncedToEntraUserTrustedForNTAuthWriteOwnerWriteOwnerLimitedRights
AdminTo edge directly in your OpenGraph payload, BloodHound removes it during post-processing and the edge does not persist in the final graph as expected. Instead of adding AdminTo edges directly, include the supporting edges that cause the post-processor to generate the AdminTo edge. The common pattern that triggers the creation of the AdminTo edge is:
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 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.
source_kind will be added to the kinds list of all nodes in the file during ingest. This feature is optional.
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.
Run:
