Skip to content

Attacks

Attacks are hook plugins (fltest/attacks/) that subclass ThreatModelBaseClass. Declare them in a config:

attacks:
  - {name: <attack>, params: {...}, target_clients: [0, 1]}   # target_clients optional (default: all)

Multiple attacks compose. target_clients restricts which clients are adversarial.

backdoor and dlg operate on pixels, so they apply only to image datasets and raise a clear error on a text run. label_flip, sign_flip, gaussian, and model_replacement work on labels or updates, so they apply to either modality.

Catalog

Name Type Hook(s) Key params
label_flip data poisoning before_client_train shift (default 1), mapping
gaussian model poisoning (naive) after_client_train sigma (0.1)
sign_flip model poisoning after_client_train scale (1.0)
model_replacement model poisoning (targeted) after_client_train scale (automatic), target_round
backdoor data poisoning (targeted) before_client_train, after_round target_label (0), infection_rate (0.3), patch_size (4), patch_value (1.0)
dlg privacy (gradient inversion) before_client_train (+ before_aggregate in shared_update mode) target_client, target_round, num_images, iters, source
membership_inference privacy (inference) on_data_distribute, after_round target_client (0), max_samples (512)

How each works

label_flip — wraps the attacker's loader and relabels each batch (y → (y+shift) % num_classes, or a fixed {src: dst} mapping). A classic robustness attack; weak alone (one of the "naive" attacks the project flags).

gaussian — adds zero-mean Gaussian noise to the attacker's update (u' = u + N(0, sigma²)). Naive Byzantine attack; useful as a baseline.

sign_flip — reflects the update around the global model and scales it (u' = g − scale·(u − g)), pushing aggregation in the opposite direction.

model_replacement — boosts a malicious local model around the current global model (u' = g + scale·(u − g)) so the malicious delta survives aggregation. This implements the train-and-scale attack from Bagdasaryan et al., How To Backdoor Federated Learning. Compose it after backdoor to boost a locally learned trigger, and set target_round for a single-shot attack. Without an explicit scale, FLTest uses num_clients / num_attackers, which is the replacement factor for full-participation, equal-weight FedAvg.

The hook interface exposes the local model, global model, client identity, and round, so the attack itself is backend-neutral on reference and Flower. It does not expose the round's total sample weight to a client, however. Automatic scaling is therefore only an estimate when clients have unequal sample weights; pass the exact factor explicitly in that case. NVFlare does not run client-side hooks and cannot apply this attack.

The runnable comparison uses one of four clients as the attacker and boosts its backdoored model only in round 3, at an automatic scale of 4.0. Replacement takes attack success from 0.2930 to 1.0000 on the reference backend and from 0.2724 to 0.9892 on Flower, costing 0.0196 and 0.0361 of clean accuracy:

Backend Attack ASR Accuracy
reference backdoor only 0.2930 0.8926
reference model replacement 1.0000 0.8730
Flower backdoor only 0.2724 0.8867
Flower model replacement 0.9892 0.8506

backdoor — the attacker stamps a bright patch on a fraction (infection_rate) of its images and relabels them to target_label; the global model learns trigger ⇒ target_label. At each round end it measures attack success rate (ASR) — the fraction of a triggered test set predicted as the target — and records it as a metric. This is the headline robustness signal; pair it with a robust-aggregation defense to see ASR drop (see Defenses).

membership_inference — asks whether a given record was in a client's training data, which is the canonical privacy attack the proposal cites and the one Pitfall-1 says evaluations skip. It models an honest-but-curious server that sees the global model each round. The score is the per-sample loss, following Yeom et al., since a model assigns lower loss to data it trained on. Members are the target client's training data and non-members are the held-out test set. It records membership_inference_auc, where 0.5 means no leakage and 1.0 means members and non-members separate perfectly, alongside membership_loss_gap. No shadow model is needed, and because it reads only losses it applies to text as readily as to images.

For example, examples/configs/membership_inference.yaml runs the same overfitted setup twice. Undefended it reaches AUC 0.67, and clipping with Gaussian noise takes it to 0.50, which is chance, for about six points of accuracy.

dlg — Deep Leakage from Gradients: reconstructs a victim client's private batch by optimizing a dummy batch so its gradient matches the victim's. Records reconstruction_mse, reconstruction_psnr, and label_recovery. Use model_name: ConvNet (smooth activations) on device: cpu. Two threat sources:

  • source: gradient (default) — reconstruct from the raw per-step gradient; demonstrates pure invertibility.
  • source: shared_update — reconstruct from the uploaded (post-defense) update; faithful only under single-step (FedSGD) training.

Examples

# label flip on two clients
attacks: [{name: label_flip, params: {shift: 1}, target_clients: [0, 1]}]
# backdoor measured by ASR
attacks: [{name: backdoor, params: {target_label: 0, infection_rate: 0.8, patch_size: 5}, target_clients: [0, 1]}]
# boost one backdoored client in round 3; scale defaults to num_clients
attacks:
  - {name: backdoor, params: {target_label: 0, infection_rate: 0.8}, target_clients: [0]}
  - {name: model_replacement, params: {target_round: 3}, target_clients: [0]}
# privacy attack
model_name: ConvNet
dataset: cifar10
attacks: [{name: dlg, params: {target_client: 0, target_round: 1, iters: 300, source: gradient}}]

Runnable: examples/configs/attack_label_flip.yaml, model_replacement.yaml, dlg.yaml.

To add your own attack, see Port your attacks & defenses.