
Исследовательский код для обучения адаптеров, позволяющих бэкдорам LLM-агентов сохраняться после доброкачественного дообучения, с оценкой частоты срабатывания триггеров, оценкой на SWE-bench и конструкторами наборов данных.
Код для "Understanding and Enhancing Backdoor Persistency in LLM Agent Post-Training" (Findings of EMNLP 2026).
📄 Статья · 🌐 Страница проекта · 📦 Датасет (с ограниченным доступом)
Бэкдор, внедрённый в модель до её выпуска, обычно разрушается в ходе доброкачественного дообучения, которое выполняет нижестоящий разработчик. PersistBD дообучает уже содержащую бэкдор модель с помощью небольшого адаптера, чтобы бэкдор пережил это обучение. На Qwen2.5-Coder-7B частота срабатывания триггера (ASR) базового бэкдора падает со 100% до 20% за 3000 шагов доброкачественного SFT; тот же бэкдор, дообученный с помощью PersistBD, сохраняется на уровне 74% (76% после последующей стадии RL), при этом доброкачественная доля решённых задач соответствует показателю базового бэкдора на SWE-bench Lite (7,7% против 6,7% после SFT; 9,0% против 9,0% после RL).
Двумя свойствами определяется, переживёт ли бэкдор доброкачественный SFT: начальная сила связи триггер→цель и её совместимость с градиентами предстоящих доброкачественных обновлений. Совместный адаптер 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/ игнорируется git, за исключением manifest.json. Загрузите набор данных с
huggingface.co/datasets/uiuc-kang-lab/PersistBD
(доступ по запросу — запросите доступ) или пересоберите его (разбиение фиксируется seed 42 в
data/manifest.json) с помощью сборщиков, запускаемых из корня репозитория:
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) | адаптеры силы / совместимости / совместный |
S, C в eval_gradient_loss.py | сила S, совместимость по градиенту C |
swe_eval_server/ интегрируется с внешним RL-тренером (verl,
не входит в комплект); одноразовая конечная точка POST /evaluate требует только Docker + SWE-bench.
Сервер привязывается к 0.0.0.0 без аутентификации и выполняет сгенерированный моделью shell внутри
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}
}