Part VIII: Industrial, Energy, and Infrastructure Sensor AI
Chapter 38: Cyber-Physical Anomaly Detection and ICS Security

Attacks vs faults

"The residual is elevated. I can tell you the tank is misbehaving. I cannot tell you whether it is tired or being lied to."

An Agnostic AI Agent

Prerequisites

This section builds directly on the physical process invariants of Section 38.1: the conserved relations and control laws whose violation raises an alarm in the first place. It assumes the residual, threshold, and change-point vocabulary of Chapter 12, and the leakage-safe train and test discipline of Chapter 5, because an attack timeline that straddles a split silently inflates every detector we compare here. Basic notions of conditional probability and base rates from Chapter 4 are used but not re-derived. No ICS protocol background (Modbus, DNP3) is assumed; the terms specific to this section (false data injection, replay, covert attack) are defined where they appear. The detector architectures that produce the residuals are deferred to Section 38.3, and hardening them against a detector-aware adversary is the job of Section 38.6.

The Big Picture

An anomaly detector on an industrial control system answers one question: is the plant departing from normal? It does not, on its own, answer the question that decides who gets paged at 3am: is this a fault, a component wearing out or a transmitter drifting, or an attack, an adversary deliberately manipulating what the controller sees or does? Both trip the same alarm, and yet the correct response could not be more different. A fault routes to maintenance and a work order; an attack routes to incident response, network isolation, and possibly law enforcement. Mistake one for the other and you either send a technician to a crime scene or you shut down a plant over a dying sensor. This section is about the information that separates the two, why it is rarely visible from the process signal alone, and how to fuse the physical and cyber layers so the detector's alarm arrives with an attribution attached.

Same alarm, opposite response

Consider a level transmitter on a storage tank that suddenly reads half a meter high. The physics-based monitor of Section 38.1 notices immediately: the mass balance no longer closes, the residual jumps, an alarm fires. That alarm is the same electrical event whether the transmitter has corroded and developed a bias, or whether an intruder on the control network is writing a false value into the register the controller reads. The detector has done its job. The operator now faces a fork that the detector did not resolve.

The distinction matters because it selects an entire downstream pipeline. A fault is a reliability event: it is handled by the prognostics and maintenance machinery of Chapter 36, it degrades along a physical trajectory you can often forecast, and its remedy is a spare part. An attack is a security event: it is handled by the security-operations workflow of Section 38.7, it is adversarially chosen rather than physically inevitable, and its remedy involves containment, forensics, and the assumption that other sensors may be compromised too. Attribution is not a philosophical nicety; it is the routing decision that determines whether the plant loses a pump or loses control.

How faults and attacks differ at the source

The two classes look alike at the alarm but arise from generative processes with different fingerprints. Naming those fingerprints is what makes discrimination possible.

Faults are nature's noise; attacks are an adversary's signal. A fault is drawn from the physics of failure: bias and drift as a sensor ages, stuck-at values when an analog-to-digital line breaks, increased variance as a bearing loosens, saturation when a range is exceeded. These modes are typically local (one transducer, one channel), uncorrelated with the plant's control commands, and often slow or physically constrained in how they evolve. A drifting thermocouple does not coordinate with anything; it just wanders.

An attack, by contrast, is optimized toward a goal. The canonical ICS attack families are worth committing to memory. False data injection (FDI) alters sensor readings so the controller acts on a lie; the smart-grid version, in which crafted meter errors slip past bad-data detection in state estimation, was formalized by Liu and colleagues in 2009. Command injection writes malicious setpoints or actuator commands directly. Replay records a stretch of normal telemetry and plays it back to mask a concurrent physical manipulation; this is the trick Stuxnet used in 2010, feeding operators recorded normal centrifuge readings while it drove the machines to destruction. Denial of service withholds or delays measurements. What unites them is that the manipulation is chosen: it can be coordinated across many sensors at once, timed to coincide with a legitimate command to hide inside expected transients, and shaped to respect the very invariants your detector checks.

Key Insight

A fault is a sample from a distribution; an attack is an adversarial input designed with your detector in mind. That single asymmetry drives every discrimination heuristic in this section. Faults tend to be marginally independent, physically constrained, and blind to your control commands. Attacks tend to be jointly coordinated, unconstrained except by the attacker's need to stay hidden, and often synchronized with network or command activity. When an anomaly is too consistent across sensors, or arrives exactly as a valve is commanded, suspect intent, not decay.

Signatures that discriminate

Four structural cues do most of the work in separating the classes, and each maps to a concrete feature you can compute.

Spatial support. Faults usually touch one sensor and break the physical relationships that couple it to its neighbors; the residual pattern points at a single node. A sophisticated attack that wants to stay hidden must instead move several sensors together to keep the invariants closing, so its signature is a coordinated shift with suspiciously low internal inconsistency. Localizing which sensors moved, and whether they moved consistently, is the root-cause problem of Section 38.5, and it is also an attribution cue.

Physical plausibility of the trajectory. Real faults follow the grammar of physics: temperatures ramp with thermal time constants, pressures cannot step instantaneously, a stuck sensor freezes but does not teleport. An attacker who does not model the plant produces changes that are physically impossible (a tank level that jumps faster than the maximum fill rate allows), which is a giveaway. An attacker who does model the plant can produce a physically plausible trajectory, which is exactly why the physical layer alone eventually runs out of discriminating power.

Correlation with the command and network layers. This is the strongest cue and the one faults cannot fake. A fault has no reason to coincide with an operator command or a write on the control network. An FDI or command-injection attack, by construction, involves traffic: a register write, an unexpected function code, a session from an unusual host. Aligning the onset of a physical anomaly with the ICS packet log is the single most reliable attack tell, and it is unavailable to any purely process-signal detector.

The too-normal signature of replay. Replay attacks invert the usual logic: the reported signal looks more normal than reality, because it is a recording of a healthy past. A detector that only asks "is this window unlike historical normal?" is defeated, since a replay is drawn from historical normal by definition. What catches replay is a model-based residual that asks "does this window respond to the command I just issued?" A frozen or looped signal fails to react to a fresh setpoint change, and that non-responsiveness, not novelty, is the fingerprint.

In Practice: the water-treatment testbed that learned to tell drift from deception

The Secure Water Treatment (SWaT) testbed at Singapore's iTrust center is a full six-stage water-purification plant instrumented for security research, and its public dataset pairs weeks of normal operation with dozens of labeled attacks. An early team built a strong reconstruction detector on the tank-level and flow signals and celebrated a high attack-detection rate. When they inspected the misses and false alarms, a pattern emerged. A slowly drifting conductivity analyzer, a genuine sensor fault, produced a residual indistinguishable from a low-and-slow FDI attack on the same channel; the process signal simply did not contain the answer. The fix was not a better reconstructor but a second evidence stream: they aligned each residual excursion with the plant's Modbus traffic. The drift had no accompanying network write and evolved on a thermal timescale, so it was routed to maintenance. The FDI onset coincided, to the second, with an unauthorized write to the analyzer's holding register from a host that had no business talking to that programmable logic controller, so it was routed to incident response. The physical layer raised the alarm; the cyber layer named the culprit.

Why the physical detector cannot decide alone

It is tempting to believe a clever enough anomaly model can read intent off the process signal. Sometimes it can, when the attacker is clumsy and violates physics. But against a competent adversary the physical layer hits a hard wall, and it is worth seeing that wall concretely. The listing below simulates a tank whose level obeys a mass-balance invariant, then injects two events with identical numerical effect: a sensor bias fault, and a false-data-injection attack that adds the same offset. The invariant residual is byte-for-byte the same in both cases, so no threshold, no matter how well tuned, can separate them. Only an exogenous signal, the network write log, breaks the tie.

import numpy as np
rng = np.random.default_rng(0)
T, onset = 400, 250

# A tank whose level follows a mass-balance invariant driven by the LOGGED inflow command.
inflow, outflow = np.ones(T), 1.0
level = np.zeros(T)
for t in range(1, T):
    level[t] = level[t - 1] + 0.1 * (inflow[t - 1] - outflow) + rng.normal(0, 0.02)

def invariant_residual(meas):                 # physics of Section 38.1, made numerical
    pred = meas[:-1] + 0.1 * (inflow[:-1] - outflow)
    return meas[1:] - pred                     # ~ zero-mean noise while the invariant holds

# (a) SENSOR FAULT: the level transmitter develops a +0.4 m bias after the onset.
fault = level.copy();  fault[onset:] += 0.4
# (b) FALSE-DATA INJECTION: an attacker adds the SAME +0.4 m to the reported level.
attack = level.copy(); attack[onset:] += 0.4

rf, ra = invariant_residual(fault), invariant_residual(attack)
print(f"peak |residual|  fault : {np.abs(rf).max():.3f}")
print(f"peak |residual| attack : {np.abs(ra).max():.3f}")
print(f"physical layer can separate them : {not np.allclose(rf, ra)}")

# The tie-breaker is EXOGENOUS: was there an unauthorized register write at the onset?
network_write_at_onset = {"fault": False, "attack": True}   # from the ICS packet log
print("attribution needs the network log :", network_write_at_onset)
Listing 38.1. A sensor bias fault and a false-data-injection attack that produce identical invariant residuals. The physical detector fires in both cases and cannot tell them apart (can separate them: False); the discriminating evidence lives in the network log, not the process signal. This is the argument for cross-domain fusion in twenty lines.

Listing 38.1 makes the section's central claim inarguable: when an attack is constructed to mimic a fault's effect on the monitored variable, the process residual carries zero information about intent. The consequence for system design is decisive. Attack-versus-fault attribution is not a harder single-signal problem; it is a fusion problem. You must join the physical residual to cyber telemetry (register writes, protocol anomalies, host and session provenance) and reason over both, a joint inference that the probabilistic fusion machinery of Chapter 9 and the Bayesian fusion of Chapter 49 are built to express.

The Right Tool

The cyber half of that fusion begins with parsing ICS network captures, and hand-writing a Modbus or DNP3 dissector to extract "who wrote which register when" is a few hundred lines of byte-level protocol code you should not maintain. The scapy library ships protocol layers that turn a packet capture into structured writes in a handful of lines:

from scapy.all import rdpcap
from scapy.contrib.modbus import ModbusPDU06WriteSingleRegister as WriteReg
writes = [(p.time, p.src, pkt.registerAddr, pkt.registerValue)
          for p in rdpcap("plant.pcap") if (pkt := p.getlayer(WriteReg))]
# each tuple = (timestamp, source host, register, value): align these with residual onsets
Listing 38.2. scapy's Modbus contrib layer collapses roughly 200 lines of manual TCP-and-protocol parsing into a comprehension that yields timestamped register writes. It handles framing and field decoding; deciding which writes are unauthorized, and correlating their timestamps with the physical residual onsets of Listing 38.1, remains the attribution logic you design.

The stealthy adversary and the limits of discrimination

The hardest case is the adversary who has read this section. A covert or stealthy attack is designed to keep every monitored residual inside its threshold while still steering the plant, exploiting the system's own dynamics so the detector never sees an excursion. The control-theory literature makes this precise: zero-dynamics attacks and covert attacks (studied by Smith, Teixeira, and others in the early 2010s) can render a manipulation entirely invisible to a residual-based monitor when the attacker knows the plant model well enough. Against such an adversary, discrimination by physical signature is not merely hard; it is provably impossible from the monitored channels alone, which is why the field increasingly relies on defenses the attacker cannot easily model, from watermarking control inputs to redundant and unpredictable sensing, and why detector robustness gets its own treatment in Section 38.6 and in the sensor-spoofing and functional-safety analysis of Chapter 68.

Research Frontier

Public ICS security benchmarks now center on the SWaT and WADI water testbeds from Singapore's iTrust and the HAI (HIL-based Augmented ICS) dataset from South Korea, all of which supply labeled attacks against a running physical process. The uncomfortable finding across recent studies is that most published detectors report detection scores while quietly conflating attacks with faults and, worse, with benign process transients; strong reported numbers often collapse once the evaluation demands attack-versus-fault attribution rather than mere anomaly flagging, and once time-aware splits (per Chapter 5) remove the transductive leakage that lets a model peek at the attack window. The live frontier is joint cyber-physical detection that ingests both process residuals and network telemetry, physics-informed models that bound what an attacker can hide, and, increasingly, LLM-driven agents (Chapter 22) that correlate an alarm with logs, tickets, and threat intelligence to propose an attribution for a human analyst.

The takeaway is a design stance, not a single algorithm. Treat every anomaly as attribution-pending. Build the physical detector to raise the alarm and localize the disturbance, then require a second, independent evidence stream, network and command telemetry, before labeling the event a fault or an attack. Where the two streams disagree or the adversary may be covert, fail toward the more expensive hypothesis: a plant that treats a possible attack as a mere fault is exactly the plant an attacker was hoping for.

Exercise

You monitor a chemical reactor with correlated temperature, pressure, and flow sensors, plus a mirror of the Modbus traffic to each PLC. (a) For each of three anomalies, propose the single most discriminating feature that separates fault from attack: (i) the pressure reading freezes at its last value, (ii) temperature and pressure both shift so the ideal-gas relation between them still holds exactly, (iii) flow drops to zero the instant an operator issues an unrelated setpoint change. (b) For anomaly (ii), explain why the physical residual is uninformative and what network-layer evidence you would seek. (c) Describe one covert attack that none of your process residuals would catch, and state what redundant or unpredictable measurement would restore detectability.

Self-Check

1. Give the one operational consequence that makes attack-versus-fault attribution worth the effort, in terms of which team is paged and what remedy each applies.

2. Explain why a replay attack defeats a novelty detector that asks "is this window unlike historical normal?" and name the alternative question that catches it.

3. In Listing 38.1 the fault and the attack produce identical residuals. State precisely what information is missing from the process signal, and where that information actually lives.

What's Next

In Section 38.3, we build the detectors that generate the residuals we have been reasoning about: reconstruction models that learn to rebuild normal operation and forecasting models that predict the next window, both of which flag an anomaly when the plant departs from what the model expected. The attack-versus-fault distinction developed here becomes the lens through which we evaluate them, because a residual is only useful once you know what its elevation is allowed to mean.