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 GuardFL, 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 GuardFL 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, GuardFL 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
-
Using the following command create a new environment, named as
secfl
conda env create -f secfl.yaml
Dataset and Checkpoint Download
- Training Dataset and Poisoned Dataset Download Link
- Placing Dataset into
/GuardFL/datafolder - Checkpoint Download Link
- Placing Model Checkpoints into
/GuardFL/checkpointfolder
MISC
You can also generate poisoned dataset of sentiment-140 and reddit datasets from scratch.
For Sentiment-140
-
GloVe Twitter WordVector Download Link
-
Placing it into
/GuardFL/preprocess/sentiment-140/.vector_cache -
Run command
cd preprocess/sentiment-140
python build_dataset.py
For Reddit
-
Original Dataset Download Link
-
Placing it into
/GuardFL/preprocess/reddit/.dataset -
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
No Attack and Defenseon 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
PGD with replacement attack and No Defenseon 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
PGD with replacement attack and G^2uardFLon 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
PGD with replacement attack and FLAMEon 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
PGD with replacement attack and G^2uardFLon 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
PGD with replacement attack and G^2uardFLon 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
PGD with replacement attack and G^2uardFLon 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
Constrain-and-Scale and G^2uardFLon 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
DBA and G^2uardFLon 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
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
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
PGD with replacement and No Defenseon 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
PGD with replacement and G^2uardFLon 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
PGD with replacement and No Defenseon 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
PGD with replacement and G^2uardFLon 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
PGD with replacement and No Defenseon 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
PGD with replacement and G^2uardFLon 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
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
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
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