Skip to content

OpenGraph Inheritance and Include All

WebbinRoot edited this page Jul 10, 2026 · 3 revisions

OpenGraph - Inheritance & Include-All

This page covers the two flags that most change OpenGraph size and shape:

  • --expand-inherited
  • --include-all

TLDR

Flag Default What It Does Typical Impact
--expand-inherited Off Fans ancestor (org/folder) IAM bindings DOWN to every descendant scope, materializing a per-descendant binding node tagged #src:<source> More reachable target scope from inherited bindings
--include-all Off Keeps generic IAM binding edges, not only high-signal dangerous-rule edges Much denser graph and more noise

--expand-inherited

Use this when you want inheritance-aware pathing. For example, if a binding is attached at the organization level, you might not see the privilege escalation in the graph if you don't factor in inheritance. --expand-inherited makes sure that the organization binding propagates downwards to the projects, which in turn can register privilege-escalation edges as they fall within an expected scope.

How it behaves:

  • With --expand-inherited: each ancestor (org/folder) binding is fanned out to every descendant scope. Each descendant gets its own binding node with a provenance suffix @<scope>#src:<source> on the binding id, and that node carries its own dangerous edges. Folder bindings inherit only downward (to child folders/projects), never up or sideways.
  • Without it (default): an ancestor binding stays attached to the ancestor only. There is no #src: suffix and descendants are not materialized for that binding, so escalations that only become visible after fan-out won't appear.

A binding that is both inherited and conditioned carries both suffixes, source first then condition (see OpenGraph - IAM Conditionals):

iambinding:roles/owner@projects/example-proj#src:<source-scope>#cond:<hash>
modules run process_og_gcpwn_data --expand-inherited --reset --out Bloodhound_Output.json

Typical use cases:

  • parent-scope IAM binding blast-radius validation
  • hierarchy-aware escalation review

--include-all

By default the pipeline collapses dangerous CAN_* relationships into the high-signal built-in edges (e.g. ROLE_OWNER/ROLE_EDITOR) and trims the generic binding edges. Use --include-all when you want broader IAM relationship coverage — it keeps the generic IAM binding edges instead of collapsing them, so you can see all bindings attached to user:alice@example.com even where the binding does not lead to privilege escalation.

modules run process_og_gcpwn_data --include-all --reset --out Bloodhound_Output.json

Typical use cases:

  • engineering/debug validation
  • custom research where you want lower-signal paths preserved

Combined Mode

modules run process_og_gcpwn_data --expand-inherited --include-all --reset --out Bloodhound_Output.json

This is maximum coverage and maximum noise.

Practical Guidance

  1. Start with default mode for fast triage and --expand-inherited to get the best results.
  2. Add --include-all only when you explicitly need exhaustive graph relationships.
  3. Add --cond-eval only when exercising conditional behavior paths. Note that conditioned bindings are emitted with a #cond:<hash> suffix regardless of the flag, and --cond-eval does not change output today (see OpenGraph - IAM Conditionals).

Clone this wiki locally