「Understanding and Enhancing Backdoor Persistency in LLM Agent Post-Training」(EMNLP 2026 Findings)のコードです。
📄 論文 · 🌐 プロジェクトページ · 📦 データセット(ゲート付き)
リリース前にモデルへ仕込まれたバックドアは、通常、下流の開発者が実行する良性のファインチューニングによって弱められます。PersistBD は、すでにバックドアを仕込まれたモデルを小さなアダプタで改良し、そのバックドアがこの学習を生き延びられるようにします。Qwen2.5-Coder-7B において、ベースのバックドアのトリガー率(ASR)は 3,000 ステップの良性 SFT を通じて 100% から 20% まで低下しますが、同じバックドアを PersistBD で改良した場合は 74% を維持します(続く RL ステージ後は 76%)。良性の解決率は SWE-bench Lite 上でベースのバックドアと同等です(SFT 後は 7.7% 対 6.7%、RL 後は 9.0% 対 9.0%)。
バックドアが良性 SFT を生き延びるかどうかを左右するのは、トリガー→ターゲットの関連付けの初期強度と、これから行われる良性の更新との勾配整合性という 2 つの性質です。PersistBD のジョイントアダプタはこの両方を高めます。論文のアブレーションは、各項がいずれも必要であることを示しています。
詳細は docs/RELEASE.md を参照してください。
| 手法コード(アダプタ学習 + マージ) | src/persistbd/ |
| トリガー率スコアラ、解決率評価、検出プローブ | eval/、src/persistbd/eval_gradient_loss.py |
| データセットビルダー + バックドア構築ヘルパー | data_processing/ |
| SWE-bench 評価サーバ(パッチ → 報酬) | swe_eval_server/ |
| バックドア済みモデルの重み | 未公開 |
| 構築済みバックドアデータセット(トリガー + 悪性ペア) | ゲート付き: uiuc-kang-lab/PersistBD |
src/persistbd/ PersistBD adapters get_delta_{s,c,j}.py, get_combined_model.py (merge),
and eval_gradient_loss.py (strength S / compatibility C)
eval/ trigger-rate scorers, eval_swe.py (SWE-bench RR), score_backdoor_logprobs.py
data_processing/ split + backdoor builders (make_*_v4.py, verify_splits_v4.py), the trigger
and malicious-pair helpers, and patch_ckpt_config.py
data/ the dataset itself (git-ignored except manifest.json)
configs/ torchtune configs for the developer's benign SFT stage
swe_eval_server/ FastAPI SWE-bench eval server used for RR and RL rewards
examples/slurm/ the jobs as we ran them, as reference templates
pip install torch transformers peft accelerate datasets pyarrow tqdm wandb vllm
# SWE-bench RR + evaluation server:
pip install -r swe_eval_server/requirements.txt
data/ は manifest.json を除いて git 管理対象外です。データセットは
huggingface.co/datasets/uiuc-kang-lab/PersistBD
からダウンロードするか(アクセス申請が必要なゲート付き)、ビルダーを使って再構築してください(分割は data/manifest.json 内のシード 42 で固定されています)。リポジトリのルートから実行します:
python data_processing/make_splits_v4.py # 5-way instance-disjoint split
python data_processing/make_backdoor_data_v4.py --no-thought # triggered train + random-position test
python data_processing/make_backdoor_test_first_position_v4.py # paired first-position test
python data_processing/verify_splits_v4.py # check the split invariants
data_processing/ 内のヘルパーにはトリガー文字列と悪意のあるコマンドが含まれています。ビルド済みデータセットが制限されている理由については
docs/RELEASE.md を参照してください。
# 1. PersistBD — train the joint adapter Δj on a backdoored checkpoint.
# Defaults reproduce the 7B arm; see the paper's table for the 3B/30B values.
torchrun --nproc_per_node=1 src/persistbd/get_delta_j.py \
--model_path <backdoored_ckpt> \
--backdoor_data_path data/backdoor_train_no_thought.jsonl \
--benign_data_path data/attacker_train.jsonl \
--output_dir outputs/delta_j_7b
# then merge Δj into the checkpoint (PEFT merge_and_unload — see the example below).
# 2. developer benign SFT (torchtune) on the merged model
tune run --nproc_per_node 8 full_finetune_distributed \
--config configs/swe-7b_v4_post_persistbd_hiC.yaml \
backdoor_dir=<merged_model> output_dir=outputs/post
# 3. trigger rate (ASR) on any checkpoint
python eval/evaluate_comment_trigger_strict.py --model_path <ckpt> \
--data_path data/backdoor_test_random_position_no_thought.json
# 4. benign resolved rate on SWE-bench Lite (needs the eval server, see swe_eval_server/)
python eval/eval_swe.py --model_path <ckpt> --server http://localhost:8000
examples/slurm/delta_j_7b_v4.sbatch(学習 + Δj のマージ)と
examples/slurm/post_7b_v4_persistbd_hiC.sbatch(benign SFT)は、ステップ 1〜2 をエンドツーエンドで実行し、
outputs/delta_j_7b_merged を介して連鎖します。
診断用の強度/互換性スイープ(Δs、Δc およびそれらの α·Δs + β·Δc グリッド)は、
get_delta_s.py、get_delta_c.py、get_combined_model.py にあります。
| コード | 論文 |
|---|---|
random_position、first_position テストセット | random-position(プライマリ)、first-position |
--lambda_bd、--lambda_c、--lambda_cl | λ_bd、λ_c、λ_cl^j |
Δs、Δc、Δj(α·Δs + β·Δc) | 強度 / 互換性 / ジョイントアダプタ |
eval_gradient_loss.py 内の S、C | 強度 S、勾配互換性 C |
swe_eval_server/ のキュー・モードは外部の RL トレーナー(verl、
含まれていません)と統合されます。ワンショットの POST /evaluate エンドポイントは Docker + SWE-bench のみを必要とします。
サーバーは認証なしで 0.0.0.0 にバインドし、モデルが生成したシェルを
Docker 内で実行します — 信頼できるネットワーク上でのみ実行してください。configs/、examples/slurm/、およびそれらの中の outputs/… パスはテンプレートです。ご自身の環境に合わせて
パスとクラスタディレクティブを編集してください。@misc{zhan2026persistbd,
title = {Understanding and Enhancing Backdoor Persistency
in LLM Agent Post-Training},
author = {Zhan, Qiusi and Lyu, Nian and Ding, Stephanie and
Mehta, Arnav and Canal, Chris and Tabarrok, Connor and
Davies, Xander and Kang, Daniel},
year = {2026},
eprint = {2610.07510},
archivePrefix = {arXiv},
primaryClass = {cs.CR},
url = {https://arxiv.org/abs/2610.07510}
}