A cyber-physical attack-graph generator for smart grids. GridShadow models the coupling between an IT-side compromise and its physical consequence on a power grid — the "shadow" an attacker casts from a phished laptop across the control network onto the physical grid — and hands the defender the shortest path from foothold to blackout so they can cut it.
One-line pitch: an AI that plays the attacker across both the network and the physics of a power grid, then ranks the chokepoints a defender should harden first.
Smart grids are coupled cyber-physical systems: an IT-side compromise can cascade through the control network into the physical grid — tripping breakers, overloading lines, shedding load. Defenders reason about the two sides separately: cyber attack graphs stop at the network boundary, and power-flow contingency analysis assumes faults are random, not adversarial. Almost nobody models the coupling. GridShadow does exactly that.
Attack graphs, power-flow simulators, and greedy search all exist. GridShadow's contributions are the connective pieces:
- A coupling formalism — a clean map
C : control assets → physical actuators, so a cyber path inherits a physical consequence (docs/coupling_formalism.md). - Adversarial contingency selection — contingencies chosen by an attacker constrained by cyber reachability, versus the random N-1/N-2 contingencies power engineers normally screen.
- Joint-objective search — optimising cyber cost and physical impact together, and ranking the resulting cyber-physical attack paths.
- The defensive inversion — turning the attacker's optimal paths into a prioritised hardening list, the practically useful output.
A run on the IEEE 14-bus case: the attacker starts from an internet-exposed IT host (ringed), pivots IT → DMZ → OT → a PLC (red path), and the PLC's coupling authorises the breaker trips that stress the grid.
== Headline joint attack ==
control assets: control-plc-0
actuations: line#6, line#0, line#3
cyber effort: 5.76 (hops=3)
impact: 35.97 | overloaded=8 lines (cascade seed)
== Defensive chokepoints (hardening ROI) ==
harden dmz-historian-0 -> ot-gateway-3 Δimpact 32.15 (89% of achievable impact)
harden ot-gateway-3 -> control-plc-0 Δimpact 32.15
The defender's headline: one well-chosen hardened edge removes ~90% of the attacker's achievable physical impact; random hardening barely moves it.
| Defender ROI | Impact vs. attacker budget |
|---|---|
![]() |
![]() |
git clone https://github.com/Krishita17/GridShadow.git
cd GridShadow
python -m venv .venv && source .venv/bin/activate
pip install -e . # or: pip install -r requirements.txtRun the full pipeline (grid → synthetic network → attacker search → defender chokepoints → figure) on the 14-bus case:
python -m gridshadow.cli run --case case14 --recommend --figures outOr the plain-API demo:
python examples/run_demo.pyReproduce every chart in this README:
python examples/sensitivity_study.py # writes out/*.pngMinimal library usage:
from gridshadow.grid.cases import load_case
from gridshadow.physics.oracle import PhysicsOracle
from gridshadow.search.joint_search import JointSearch
from gridshadow.synth.generator import ScenarioConfig, generate_scenario
net = load_case("case14")
scenario = generate_scenario(net, ScenarioConfig(seed=7, segmentation_level=0.7))
oracle = PhysicsOracle(net)
attack = JointSearch(scenario.graph, scenario.coupling, oracle).greedy_attack(
cyber_budget=6.0, max_actuations=3
)
print(attack.summary())asset/recon model -> cyber reachability graph -> coupling map -> physics oracle
(OSINT view) (lateral movement) (cyber→actuator) (power-flow impact)
\___________ joint search ___________/
|
ranked attack paths + chokepoints
- Grid (
gridshadow.grid) — loads IEEE test cases (14/30/57/118 bus) via pandapower. - Cyber layer (
gridshadow.cyber) — a MulVAL-style reachability/exploit graph over assets tagged with services and ICS weakness categories. - Coupling map (
gridshadow.coupling) — the novel link from reachable control assets to the actuations they authorise. - Physics oracle (
gridshadow.physics) — steady-state power flow scoring lost load + overload severity. Because the public cases lack realistic thermal limits, it derives security-margin ratings from base-case flows (standard contingency-screening practice; see the module docstring). - Joint search (
gridshadow.search) — Dijkstra reachability under a cyber budget + greedy submodular actuation selection under a physical budget. - Recommender (
gridshadow.recommender) — removes cyber edges to find the chokepoints that most reduce achievable impact, and the ROI curve. - Synthetic generator (
gridshadow.synth) — reproducible IT/OT overlays with tunable segmentation, patch coverage, exposure, and coupling density.
Full write-up: docs/architecture.md · docs/coupling_formalism.md.
- Attacker quality — joint search finds strictly higher-impact paths than a
random-reachable baseline (see
budget_impact.png). - Defender value — targeted chokepoints reduce achievable impact far more
per edge than random hardening (
chokepoint_roi.png): the headline result. - Sensitivity — how achievable impact scales with network segmentation and
patch coverage (
sensitivity_seg.png,sensitivity_patch.png). - Correctness — the physics oracle is validated against pandapower baselines
and the base case is verified secure under derived ratings (see
tests/).
pip install pytest && pytest -q # 15 tests- Tier 1 (done): static end-to-end on 14/30-bus — cyber graph, coupling map, joint search, steady-state oracle, ranked paths + impact table.
- Tier 2 (done): chokepoint recommender + ROI, synthetic generator, and the segmentation / patch-coverage sensitivity study.
- Tier 3 (roadmap): RL attacker on 118-bus; cascading-failure dynamics in the oracle; RL-vs-search scaling curves.
Defensive research only. GridShadow runs entirely on simulated grids and synthetic networks built from public benchmarks. The coupling map is modelled, not discovered from any real utility. It contains no exploit code, no real target, and no detection-evasion tooling — it produces a defender's deliverable: where to harden first. See docs/threat_model.md.
See CITATION.cff.
MIT © Krishita Sanjay Choksi


