GuardFL: Safeguarding Federated Learning Against Backdoor Attacks via Attributed Client Graph Clustering

March 30, 2026 · View on GitHub

Abstract

As a collaborative paradigm, Federated Learning (FL) empowers clients to engage in collective model training without exchanging their respective local data. Nevertheless, FL remains vulnerable to backdoor attacks in which an attacker compromises malicious clients, and injects poisoned model weights into the aggregation process to yield attacker-chosen predictions for particular samples. Existing countermeasures, mainly based on anomaly detection, may erroneously reject legitimate weights while accepting malicious ones, which is due to inadequacies in quantifying client model similarities. Other defense mechanisms prove effective exclusively when confronted with a restricted number of malicious clients, e.g., less than 10%. To address these vulnerabilities, we present G2{}^2uardFL, a protective framework that reframes the detection of malicious clients as an attributed client graph clustering problem. This framework employs a graph clustering technique to identify malicious clients and incorporates an adaptive method to amplify the disparity between the aggregated model and poisoned client models, thereby eliminating previously embedded backdoors. A theoretical analysis of convergence is also performed to demonstrate that the global model closely approximates the model untouched by any backdoor. Through empirical evaluation compared to cutting-edge defenses and against various backdoor attacks, our experimental results indicate that G2^2uardFL considerably undermines the effectiveness of backdoor attacks while maintaining a negligible impact on the benign sample performance. For instance, in an FL system with 25% malicious clients, G2^2uardFL can reduce the attack success rate to a mere 1.67%, while maintaining a remarkable benign sample performance of 84.84% on the CIFAR-10 dataset. This surpasses the performance of the best-performing baseline, which achieves a performance of 9.31% on benign samples.

Preparations

Conda Environment Installation

  1. First, please install miniconda or anaconda

  2. Using the following command create a new environment, named as secfl

conda env create -f secfl.yaml

Dataset and Checkpoint Download

  1. Training Dataset and Poisoned Dataset Download Link
  2. Placing Dataset into /GuardFL/data folder
  3. Checkpoint Download Link
  4. Placing Model Checkpoints into /GuardFL/checkpoint folder

MISC

You can also generate poisoned dataset of sentiment-140 and reddit datasets from scratch.

For Sentiment-140

  1. GloVe Twitter WordVector Download Link

  2. Placing it into /GuardFL/preprocess/sentiment-140/.vector_cache

  3. Run command

cd preprocess/sentiment-140
python build_dataset.py

For Reddit

  1. Original Dataset Download Link

  2. Placing it into /GuardFL/preprocess/reddit/.dataset

  3. Run command

cd preprocess/reddit
python build_dataset.py

Init Logger

This repo utilizes the wandb package to log the training process. Thus, please following the instructions of its Official GitHub Repo to configure the wandb.

Note that, after configuring it, please update project name in the line 261 of main.py.

Running

Effectiveness

  1. No Attack and Defense on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 2 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method no-defense --attack_method blackbox --attack_case normal-case --model_replacement False --project_frequency 10 --stddev 0.025 --eps 5 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --test_batch_size 1024 --instance "CIFAR10 with No-Attack-And-Defense" --wandb_group Effectiveness
  1. PGD with replacement attack and No Defense on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method no-defense --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-No-Defense" --wandb_group Effectiveness
  1. PGD with replacement attack and G^2uardFL on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method guardfl --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --kappa1 0.1 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta1 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-GuardFL" --wandb_group Effectiveness
  1. PGD with replacement attack and FLAME on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method flame --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-FLAME" --wandb_group Effectiveness
  1. PGD with replacement attack and G^2uardFL on MNIST
python main.py --lr 0.01 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset mnist --model lenet --fl_mode fixed-pool --defense_method guardfl --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 0.2 --adv_lr 0.01 --prox_attack False --poison_type ardis --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --kappa1 0.1 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta1 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 1024 --instance "MNIST with PGD-Replace-And-GuardFL" --wandb_group Effectiveness
  1. PGD with replacement attack and G^2uardFL on Reddit
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 2 --dataset reddit --model word_predict --fl_mode fixed-pool --defense_method guardfl --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 2 --adv_lr 0.02 --prox_attack False --poison_type None --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --kappa1 0.1 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta1 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 128 --instance "Reddit with PGD-Replace-And-GuardFL" --wandb_group Effectiveness
  1. PGD with replacement attack and G^2uardFL on Sentiment-140
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 2 --dataset sentiment140 --model text_bc --fl_mode fixed-pool --defense_method guardfl --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 2 --adv_lr 0.02 --prox_attack False --poison_type greek-backdoor --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --kappa1 0.1 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta1 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 256 --instance "Sentiment140 with PGD-Replace-And-GuardFL" --wandb_group Effectiveness

Robustness

Typical Attacks

  1. Constrain-and-Scale and G^2uardFL on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method guardfl --attack_method prox --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack True --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --kappa1 0.1 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta2 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 1024 --instance "CIFAR10 with Prox-Replace-And-GuardFL" --wandb_group Robustness
  1. DBA and G^2uardFL on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method guardfl --attack_method dba --attack_case normal-case --model_replacement False --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type four_points --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --kappa1 0.1 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta2 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 1024 --instance "CIFAR10 with DBA-And-GuardFL" --wandb_group Robustness
  1. No Attack and Defense Non-iid(1.0) on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 2 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method no-defense --attack_method blackbox --attack_case normal-case --model_replacement False --project_frequency 10 --stddev 0.025 --eps 5 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0 --pdr 0.5 --degree_nonIID 1.0 --use_trustworthy True --device cuda:0 --test_batch_size 1024 --instance "CIFAR10 with No-Attack-And-Defense-Noniid(1.0)" --wandb_group Robustness
  1. PGD with replacement and G^2uardFL Non-iid(1.0) on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method guardfl --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 1.0 --use_trustworthy True --device cuda:0 --kappa1 0.1 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta1 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-GuardFL-Noniid(1.0)" --wandb_group Robustness

Adaptive Attacks

Varying PDR
  1. PGD with replacement and No Defense on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method no-defense --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-No-Defense (Varying PDR)" --wandb_group Robustness --vary_pdr --pdr_low 0.05 --pdr_high 0.20
  1. PGD with replacement and G^2uardFL on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method no-defense --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-No-Defense (Varying PDR)" --wandb_group Robustness --vary_pdr --pdr_low 0.05 --pdr_high 0.20
Model Obfuscation
  1. PGD with replacement and No Defense on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method no-defense --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-No-Defense (Model Obfuscation)" --wandb_group Robustness --model_obfuscation --noise_level 0.034
  1. PGD with replacement and G^2uardFL on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method guardfl --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --kappa1 0.1 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta1 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-GuardFL (Model Obfuscation)" --wandb_group Robustness --model_obfuscation --noise_level 0.034
Fixed Frequency
  1. PGD with replacement and No Defense on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-freq --defense_method no-defense --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-No-Defense (Fixed Frequency)" --wandb_group Robustness
  1. PGD with replacement and G^2uardFL on CIFAR-10
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-freq --defense_method guardfl --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --kappa1 0.1 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta1 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-GuardFL (Fixed Frequency)" --wandb_group Robustness

Sensitivity

  1. PMR = 0.1
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method guardfl --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.10 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --kappa1 0.1 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta1 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-GuardFL-PMR(0.10)" --wandb_group Sensitivity
  1. M = 0.05
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method guardfl --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --kappa1 0.1 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta1 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-GuardFL-Drop_Rate(0.05)" --wandb_group Sensitivity --simulate_real --client_drop_rate 0.05
  1. κ1=0.0\kappa_1 = 0.0
python main.py --lr 0.02 --gamma 0.998 --num_nets 200 --fl_round 600 --part_nets_per_round 10 --local_train_period 2 --adversarial_local_training_period 8 --dataset cifar10 --model vgg9 --fl_mode fixed-pool --defense_method guardfl --attack_method pgd --attack_case normal-case --model_replacement True --project_frequency 10 --stddev 0.025 --eps 1.0 --adv_lr 0.02 --prox_attack False --poison_type southwest --norm_bound 2 --attacker_percent 0.25 --pdr 0.5 --degree_nonIID 0 --use_trustworthy True --device cuda:0 --kappa1 0.0 --kappa2 0.1 --kappa3 0.5 --kappa4 0.3 --optimizer Adam --epochs_pretrain 200 --epochs_cluster 200 --lr_pretrain 0.01 --lr_cluster 0.01 --beta1 0.30 --beta1 0.15 --alpha1 1.0 --alpha2 0.001 --activation ReLU --test_batch_size 1024 --instance "CIFAR10 with PGD-Replace-And-GuardFL-Kappa1(0.0)" --wandb_group Sensitivity