
Código de investigación para entrenar adaptadores que hacen que las puertas traseras de agentes LLM sobrevivan a un ajuste fino benigno, con puntuación de tasa de activación, evaluación SWE-bench y constructores de conjuntos de datos.
Código para "Understanding and Enhancing Backdoor Persistency in LLM Agent Post-Training" (Findings of EMNLP 2026).
📄 Artículo · 🌐 Página del proyecto · 📦 Conjunto de datos (con acceso restringido)
Una puerta trasera implantada en un modelo antes de su publicación normalmente se ve erosionada por el ajuste fino benigno que ejecuta un desarrollador posterior. PersistBD refina un modelo ya comprometido con una puerta trasera mediante un pequeño adaptador para que la puerta trasera sobreviva a ese entrenamiento. En Qwen2.5-Coder-7B, la tasa de activación (ASR) de una puerta trasera base cae del 100% al 20% a lo largo de 3.000 pasos de SFT benigno; la misma puerta trasera refinada con PersistBD se mantiene en el 74% (76% tras la etapa posterior de RL), con una tasa de resolución benigna que iguala la de la puerta trasera base en SWE-bench Lite (7,7% frente a 6,7% tras SFT; 9,0% frente a 9,0% tras RL).
Dos propiedades determinan si una puerta trasera sobrevive al SFT benigno: la fuerza inicial de la asociación disparador→objetivo y su compatibilidad de gradiente con las actualizaciones benignas que vendrán. El adaptador conjunto de PersistBD incrementa ambas; la ablación del artículo muestra que cada término es necesario.
Consulta docs/RELEASE.md para más detalles.
| Código del método (entrenamiento del adaptador + fusión) | src/persistbd/ |
| Evaluadores de tasa de activación, evaluación de tasa de resolución, sondas de detección | eval/, src/persistbd/eval_gradient_loss.py |
| Constructores de conjuntos de datos + utilidades de construcción de puertas traseras | data_processing/ |
| Servidor de evaluación de SWE-bench (parche → recompensa) | swe_eval_server/ |
| Pesos del modelo con puerta trasera | no publicados |
| Conjunto de datos de puertas traseras construido (pares de disparador + maliciosos) | con acceso restringido: 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/ está ignorado por git excepto manifest.json. Descarga el conjunto de datos desde
huggingface.co/datasets/uiuc-kang-lab/PersistBD
(con acceso restringido — solicita acceso), o vuelve a construirlo (la división está fijada por la semilla 42 en
data/manifest.json) con los constructores, ejecutados desde la raíz del repositorio:
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
Los helpers en data_processing/ contienen la cadena de activación y el comando malicioso; consulta
docs/RELEASE.md para saber por qué el conjunto de datos compilado está restringido.
# 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 (entrenamiento + fusión de Δj) y
examples/slurm/post_7b_v4_persistbd_hiC.sbatch (SFT benigno) ejecutan los pasos 1–2 de principio a fin
y encadenan a través de outputs/delta_j_7b_merged.
El barrido de diagnóstico de fuerza/compatibilidad (Δs, Δc y su cuadrícula α·Δs + β·Δc) está en
get_delta_s.py, get_delta_c.py y get_combined_model.py.
| código | artículo |
|---|---|
conjuntos de prueba random_position, first_position | posición aleatoria (principal), primera posición |
--lambda_bd, --lambda_c, --lambda_cl | λ_bd, λ_c, λ_cl^j |
Δs, Δc, Δj (α·Δs + β·Δc) | adaptadores de fuerza / compatibilidad / conjuntos |
S, C en eval_gradient_loss.py | fuerza S, compatibilidad de gradiente C |
swe_eval_server/ se integra con un entrenador RL externo (verl,
no incluido); el endpoint de un solo uso POST /evaluate solo necesita Docker + SWE-bench.
El servidor se enlaza a 0.0.0.0 sin autenticación y ejecuta shell generado por el modelo dentro de
Docker — ejecútalo únicamente en una red de confianza.configs/, examples/slurm/ y las rutas outputs/… que contienen son plantillas; edita
las rutas y las directivas del clúster para tu entorno.@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}
}