Skip to content

Vect0rdecay/GraphSurgeon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GraphSurgeon

GraphSurgeon reverse-engineers ONNX computational graphs from the command line or Python. It summarizes inputs and operators, maps depth and execution order, detects structural motifs in the DAG, cross-references adversarial ML literature, narrates data flow, and supports counterfactual edits with validation and diff.

The tool is ONNX-only. It does not require PyTorch or a CUDA toolkit.

What it does

Command Role
inspect Model summary: I/O tensors, initializer count, operator mix
topology Graph depth, early/middle/late layer buckets, execution order
patterns Coarse structural blocks (conv stacks, attention, normalization chains)
motifs Registry-backed structural motifs: which attack classes the graph topology makes architecturally plausible
flow Plain-English execution narrative
catalog Lookup gadgets, compound chains, literature techniques, and bundled paper notes
operators ONNX operator reference keyed to security-relevant behavior
edit Counterfactual graph surgery (remove-node) with structural, loadable, or runnable validation
diff Compare two ONNX files after edits

Motif hits describe attack landscape (what attack types the architecture enables), not confirmed exploitability. The tool does not assign risk scores or severity tiers.

Install

cd graph-surgeon
python3 -m venv .venv
.venv/bin/python -m pip install -e ".[dev]"
Package Purpose
onnx, numpy Core graph parsing, motifs, topology (always installed)
onnxruntime edit validate --level loadable/runnable (via [dev])
pytest Test suite (via [dev])

Minimal install (no runtime validation or tests):

.venv/bin/python -m pip install -e .

CLI

After pip install -e ., use the project venv (the graph-surgeon command is not on your system PATH unless you activate the venv):

source .venv/bin/activate   # optional; then graph-surgeon works on PATH
# or always:
.venv/bin/graph-surgeon --help
.venv/bin/python -m graph_surgeon catalog --coverage
graph-surgeon inspect model.onnx
graph-surgeon topology model.onnx
graph-surgeon patterns model.onnx
graph-surgeon motifs model.onnx -o report.json
graph-surgeon flow model.onnx
graph-surgeon catalog --gadget GAP_FC_HEAD
graph-surgeon catalog --chain CHAIN-PATCH-ATTACK-SURFACE
graph-surgeon catalog --coverage
graph-surgeon operators --op Conv
graph-surgeon edit validate edited.onnx --level runnable
graph-surgeon edit remove-node model.onnx NODE_NAME -o edited.onnx
graph-surgeon diff baseline.onnx edited.onnx

When a motif or chain is detected, use catalog --gadget or catalog --chain for registry metadata, detection logic, and paper write-ups. Display titles use registry IDs (for example GAP_FC_HEAD — Global Average Pool → FC Head).

Counterfactual edits (edit) currently expose one surgery subcommand: remove-node. Use inspect or topology to discover exact ONNX node names before editing.

Research corpus

GraphSurgeon ships per-paper analysis under graph_surgeon/taxonomy/data/ (notably attack_research_notes.md). That corpus is what powers rich catalog output: when you look up a gadget or chain, you get the linked AML literature, ONNX graph indicators, and attack-class mapping without fetching external docs.

Normal use does not require touching these files. To see completion status:

.venv/bin/graph-surgeon catalog --coverage

Python API

GraphSurgeon is primarily a CLI tool, but the same analysis and surgery paths are available from Python. Package-level exports (from graph_surgeon import ...): GraphSurgeon, GraphTopology, GraphTopologyConfig, LayerPosition, NodeTopology, GraphValidationLevel, GraphValidationResult.

Analysis (motifs, patterns, flow)

These mirror motifs, patterns, and flow:

from graph_surgeon.parsers.onnx_parser import analyze_onnx_graph, analyze_onnx_patterns, quick_scan

motif_report = analyze_onnx_graph("model.onnx", output_path="report.json")
print(len(motif_report.structural_findings), motif_report.model_flow_description)

pattern_report = analyze_onnx_patterns("model.onnx")
print(quick_scan("model.onnx"))

JSON export from motifs uses the same sanitizer as CLI output (internal scoring fields stripped).

Topology and graph inspection

from graph_surgeon import GraphSurgeon, LayerPosition

surgeon = GraphSurgeon(verbose=False)
model = surgeon.load_model("model.onnx")
topo = surgeon.get_graph_topology(model.graph)

print(topo.total_nodes, topo.max_depth)
print(topo.by_position[LayerPosition.EARLY][:5])
print(topo.by_position[LayerPosition.LATE][:5])
print(surgeon.find_nodes_by_type(model.graph, "Conv"))

Catalog and taxonomy

These mirror catalog lookups:

from graph_surgeon.taxonomy.display import format_catalog_gadget, format_catalog_chain
from graph_surgeon.taxonomy.research_coverage import format_coverage_report
from graph_surgeon.taxonomy import motif_catalog

print(format_catalog_gadget("LINEAR_HEAD"))
print(format_catalog_chain("CHAIN-SKIP-HIGHWAY"))
print(format_coverage_report())
technique = motif_catalog.get_technique_by_id("AML-ADV-002")

Counterfactual edits

CLI parity: remove_node matches edit remove-node. All surgery methods mutate the loaded ModelProto in place and return a SurgeryResult (success, message, nodes_removed, edges_rewired, etc.).

from graph_surgeon import GraphSurgeon, GraphValidationLevel

surgeon = GraphSurgeon(verbose=False)
baseline = surgeon.load_model("model.onnx")
edited = surgeon.clone_model(baseline)

result = surgeon.remove_node(edited, "node_relu_23")
if not result.success:
    raise RuntimeError(result.message)

surgeon.save_model(edited, "edited.onnx")

check = surgeon.validate(edited, level=GraphValidationLevel.STRUCTURAL)
print(check.valid, check.errors)

diff = surgeon.compare_graphs(baseline, edited)
print(diff["summary"], diff["nodes_removed"])

GraphValidationLevel.LOADABLE and .RUNNABLE require onnxruntime (installed with pip install -e ".[dev]"). On a minimal install, validation falls back with warnings.

Additional graph surgery primitives (remove_subgraph, insert_node_before, insert_node_after, replace_node, modify_node_attribute, add_initializer, add_metadata) are Python-only today. See docs/PYTHON_API.md for the full GraphSurgeon reference.

Optional weight statistics

Heuristic weight-distribution analysis (core deps only; no onnxruntime):

from graph_surgeon.behavior.weight_signature import analyze_onnx_weights

stats = analyze_onnx_weights("model.onnx")
print(stats.summary())

Documentation

Doc Contents
docs/PYTHON_API.md Full GraphSurgeon method reference, validation levels, surgery result fields

Comparison to Netron

Netron is a graph viewer: nodes, tensors, and shapes on screen.

GraphSurgeon is an analysis and experimentation layer on top of the same ONNX files:

  • Positional topology (stem vs middle vs head) and ordered execution, not just adjacency
  • Automated motif and pattern detection with a typed registry and literature cross-reference
  • A searchable catalog of gadgets, chains, techniques, and bundled paper notes
  • Counterfactual edits (remove a node, rewire, validate, diff against baseline)
  • JSON export for scripting and batch comparison across model variants

Use Netron to see the graph; use GraphSurgeon to interpret structure, relate it to published attack classes, and test what changes when you alter the DAG.

Tests

Unit tests (no external ONNX files):

.venv/bin/python -m pytest tests/ -v

Integration tests that require off-repo ONNX fixtures are gitignored and documented in tests/README.md.

License

MIT

About

ONNX computational graph reverse engineering: topology, structural motifs, literature catalog, and counterfactual edits.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages