RetroPatch is an LLM-assisted patch backporting toolkit. It takes a fix commit from a newer upstream revision, analyzes why the patch does not apply cleanly to an older target revision, and iteratively generates a target-version patch with tool feedback from Git, symbol lookup, source-code inspection, compilation, testcases, and PoC validation.
The repository also includes a prejudge pipeline for kernel-oriented workflows. That pipeline decides whether a candidate upstream fix is worth backporting to a target tree before running the heavier patch-generation workflow.
RetroPatch automates the common backporting loop:
- Read a known fix commit and split it into patch hunks.
- Try to apply each hunk directly to the target revision.
- If a hunk conflicts, use an LLM agent with repository tools to locate the corresponding old code and rewrite the hunk.
- Join all successful hunks into a complete patch.
- Validate the patch by applying it, building the target project, running regression tests, and checking whether the PoC still triggers the bug.
- Save logs and the final successful patch information for review.
The tool is designed for security and maintenance backports where the target branch may differ from upstream through moved code, renamed symbols, changed context, or partially absent logic.
src/backporting.py Main backporting CLI
src/example.yml Example case configuration
src/agent/ LLM prompts and agent orchestration
src/tools/ Git, patch, symbol, validation, and logging helpers
src/prejudge/ Kernel pre-backport judgment pipeline
test/ Helper scripts for hunk, patch, and prejudge testing
docs/ Architecture, safety, configuration, tools, and evaluation docs
skills/retropatch-engineering/
Local Codex skill for repository-specific work
Dockerfile Containerized runtime
- Architecture
- Runtime Safety
- Configuration Reference
- Provider Configuration
- Tool Contracts
- Evaluation
- Prompt Design
- Python 3.10 or newer
- Git
- Universal Ctags (
ctags) for symbol indexing - A disposable clone of the target project
- Optional build dependencies required by the target project
- OpenAI, DeepSeek, or Azure OpenAI provider credentials for the main workflow
OPENROUTER_API_KEYif you run the prejudge LLM tools
Install Python dependencies:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtIf you use uv:
uv syncRetroPatch modifies the configured project_dir while running. The main
workflow calls Git cleanup operations, including hard reset and removal of
untracked files, inside the target repository.
Use a dedicated throwaway clone for project_dir. Do not point the tool at a
working tree that contains uncommitted work or important untracked files.
Validation scripts from patch_dataset_dir are copied into project_dir before
final validation. If files with the same names already exist in project_dir,
they may be replaced.
- Prepare a clean target-project clone.
git clone <project-url> dataset/<project-name>- Prepare a case directory containing optional validation scripts.
patch_dataset_dir/
build.sh optional; builds the patched target
test.sh optional; runs regression tests
poc.sh optional; runs the bug trigger / PoC
Public benchmark cases are available in the OS3Lab patch dataset:
https://github.com/OS3Lab/patch_dataset. Each case directory can be used as
patch_dataset_dir after cloning the corresponding target project repository.
If a script is absent, RetroPatch treats that validation stage as passed.
- Copy and edit the example configuration.
cp src/example.yml case.yml- Run the backporting agent.
python src/backporting.py --config case.ymlUse debug mode for verbose agent and tool logs:
python src/backporting.py --config case.yml --debugRuntime logs are created under ../logs relative to the current working
directory and copied into patch_dataset_dir at the end of a run.
Example:
project: libtiff
project_url: https://github.com/libsdl-org/libtiff
new_patch: 881a070194783561fd209b7c789a4e75566f7f37
new_patch_parent: 6bb0f1171adfcccde2cd7931e74317cccb7db845
target_release: 13f294c3d7837d630b3e9b08089752bc07b730e6
sanitizer: LeakSanitizer
error_message: "ERROR: LeakSanitizer"
tag: CVE-2023-3576
openai_key: sk-...
project_dir: dataset/libsdl-org/libtiff
patch_dataset_dir: ~/backports/patch_dataset/libtiff/CVE-2023-3576/
llm_provider: openai
llm_model: gpt-4-turbo
llm_base_url: https://api.openai.com/v1
llm_temperature: 0.5
llm_max_tokens:
llm_thinking:
use_azure: false
# azure_endpoint: "https://your-resource.openai.azure.com/"
# azure_deployment: "gpt-5"
# azure_api_version: "2024-12-01-preview"Field reference:
project: Human-readable project name used in logs.project_url: Upstream repository URL, used as context for the agent.new_patch: Upstream fixed commit to backport.new_patch_parent: Parent commit ofnew_patch, representing the newer vulnerable revision before the fix.target_release: Older target commit or revision that needs the fix.sanitizer: Optional case metadata for the sanitizer used by the PoC.error_message: Text expected in PoC output when the bug is still triggered.tag: Case identifier, commonly a CVE or bug ID.openai_key: API key for the main backporting agent.llm_provider,llm_model,llm_base_url,llm_temperature,llm_max_tokens,llm_thinking: Optional OpenAI-compatible model settings. For DeepSeek, setllm_provider: deepseekand provide the key withDEEPSEEK_API_KEYordeepseek_key.project_dir: Local target-project Git repository.patch_dataset_dir: Case directory containing validation scripts and copied logs.use_azure,azure_endpoint,azure_deployment,azure_api_version: Optional Azure OpenAI settings.
The required commits must all exist in project_dir; the loader resolves them
to full commit hashes before the run starts.
newer vulnerable revision --new_patch--> newer fixed revision
|
| backport fix
v
older target revision ----generated patch----> fixed older target
For each hunk, the agent can use these tools:
viewcode: inspect source code at a specific path and revision.locate_symbol: locate a function or symbol using Ctags.git_history: inspect history for lines related to the current hunk.git_show: inspect a relevant historical commit.validate: apply a hunk or complete patch and return concrete feedback.
After all hunks apply, RetroPatch validates the complete patch in this order:
- Apply the complete patch to
target_release. - Run
build.shif present. - Run
test.shif present. - Run
poc.shif present and check thaterror_messageno longer appears.
The prejudge pipeline is useful when processing many kernel fixes. It filters cases before full backporting by checking dependency/fix commits, architecture and config relevance, and whether vulnerable code appears in the target tree.
Single commit:
export OPENROUTER_API_KEY=<your-key>
python src/prejudge/prejudge.py <commit-id> <kernel-source-dir> <target-project-dir>Batch CSV:
python test/test_prejudge.py <input.csv> <output.csv> <kernel-source-dir> <target-project-dir>The input CSV should contain CVE-ID, Mainline_Commit, and Status columns.
The output CSV adds a Prejudge_Result column.
The LLM-based judge can also be run directly:
python src/prejudge/judge_agent.py <commit-id> <src-project-path> <target-project-path> [model-provider]Supported provider names are openai, deepseek, gemini, and claude.
Build the image:
docker build -t retropatch .Run with mounted project and dataset directories:
docker run --rm \
-v "$(pwd)":/app \
-v /path/to/dataset:/path/to/dataset \
retropatch \
python backporting.py --config /app/case.ymlInteractive shell:
docker run --rm -it \
-v "$(pwd)":/app \
-v /path/to/dataset:/path/to/dataset \
retropatch /bin/bashCheck local setup:
python3 skills/retropatch-engineering/scripts/check_setup.py
python3 skills/retropatch-engineering/scripts/check_setup.py --config case.ymlRun helper validation scripts:
python test/test_patch.py --config case.yml
python test/test_prejudge.py test.csv test_results.csv data/linux data/kerneltest/test_patch.py and test/test_hunk.py are development helpers. They
contain embedded patch examples and may need editing for a specific case before
use.
Commit id ... is invalid: the configured commit does not exist inproject_dir.Project directory does not exist:project_dirmust point to a local Git checkout.- Ctags errors or missing symbol results: install Universal Ctags and confirm
ctagsis onPATH. - Patch applies but validation passes too quickly: check whether
build.sh,test.sh, orpoc.share missing frompatch_dataset_dir; missing scripts are treated as passed. - Prejudge API errors: set
OPENROUTER_API_KEYforsrc/prejudge/*tools.
This repository includes a local Codex skill at
skills/retropatch-engineering/.
Use $retropatch-engineering when working on RetroPatch-specific tasks such as
pipeline changes in src/backporting.py, src/agent/, src/tools/, prejudge
changes in src/prejudge/, or documentation updates that depend on this
workflow.