Skip to content

CVE-2026-58169: Verified Repro With Script Download

CVE-2026-58169: Vibe-Trading DNS rebinding authentication bypass leading to RCE

CVE-2026-58169 is verified against the affected target. Vulnerability class: RCE. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00254.

REPRO-2026-00254 RCE Variant found Jul 6, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
7.5
Confidence
HIGH
Reproduced in
18m 8s
Tool calls
239
Spend
$3.88
01 · Overview

What Is CVE-2026-58169?

CVE-2026-58169 is a high-severity DNS rebinding authentication bypass (CWE-346) in Vibe-Trading that lets an unauthenticated attacker bypass API authentication and reach a remote code execution primitive. Pruva reproduced it (reproduction REPRO-2026-00254).

02 · Severity & CVSS

CVE-2026-58169 Severity & CVSS Score

CVE-2026-58169 is rated high severity, with a CVSS base score of 7.5 out of 10.

HIGH threat level
7.5 / 10 CVSS base
Weakness CWE-346 (Origin Validation Error)

High — serious impact or readily exploitable. Prioritize remediation.

How to Reproduce CVE-2026-58169

$ pruva-verify REPRO-2026-00254
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00254/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-58169

Remote code execution — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

DNS-rebound Host header (rebind.attacker.test:8899) with no bearer token, sent via curl --resolve to 127.0.0.1

Attack chain
  1. DNS rebinding
  2. loopback TCP peer
  3. _is_local_client() bypasses API_AUTH_KEY
  4. _shell_tools_enabled_for_request() enables bash tool
  5. POST /sessions/{id}/messages
  6. BashTool subprocess.run(shell=True)
  7. RCE
Variants tested

Partial bypass of the v0.1.10 Host-validation fix (PR #242): the production loopback-Host allowlist _DEFAULT_LOOPBACK_HOSTS includes the non-loopback test hostname 'testserver', so a loopback peer with Host: testserver:<port> and no bearer token is auth-bypassed on the fixed v0.1.10 (POST /sessions -> 201). In the def…

How the agent worked 541 events · 239 tool calls · 18 min
18 minDuration
239Tool calls
123Reasoning steps
541Events
2Dead-ends
Agent activity over 18 min
Support
18
Repro
300
Judge
35
Variant
184
0:0018:08

Root Cause and Exploit Chain for CVE-2026-58169

Versions: Vibe-Trading < 0.1.10 (confirmed on v0.1.9, commit 8cebccb9b301f962d11bf0fa8c6be9bf7d7e12f2)Fixed: v0.1.10 (commit 54f944743efee7b9cbaaeafb5966c583d0d4ac66), via PR #242 (6e06017) — adds _reject_untrusted_loopback_host middleware

Vibe-Trading before v0.1.10 contains a DNS rebinding authentication bypass vulnerability (CWE-346 Origin Validation Error). The FastAPI API server (agent/api_server.py) binds to 0.0.0.0 by default and treats any TCP connection from a loopback peer address (127.0.0.1, ::1, localhost) as a trusted local/dev-mode caller, bypassing API_AUTH_KEY bearer-token authentication entirely. Because the server performs no Host header validation on loopback-trusted requests, an attacker can use DNS rebinding to make a victim's browser issue same-origin JSON requests to the local API with an attacker-controlled Host header and no bearer token. The loopback peer IP causes _is_local_client() to return True, so _validate_api_auth() skips authentication. Furthermore, _shell_tools_enabled_for_request() returns True for loopback clients, enabling the bash tool in the agent's tool registry. The attacker can then send a message to a session that triggers the BashTool, which executes subprocess.run(command, shell=True) — achieving remote code execution as the API process user. The attacker can also overwrite LLM and data-source settings to exfiltrate credentials.

  • Package/component affected: HKUDS/Vibe-Tradingagent/api_server.py (loopback trust/auth boundary, Host-header validation), agent/src/tools/bash_tool.py (BashTool RCE primitive), agent/src/tools/__init__.py (shell tool gating)
  • Affected versions: Vibe-Trading < 0.1.10 (confirmed on v0.1.9, commit 8cebccb9b301f962d11bf0fa8c6be9bf7d7e12f2)
  • Fixed version: v0.1.10 (commit 54f944743efee7b9cbaaeafb5966c583d0d4ac66), via PR #242 (6e06017) — adds _reject_untrusted_loopback_host middleware
  • Risk level: High (CVSS 7.7 / 8.1)
  • Consequences: Unauthenticated remote code execution as the API process user; unauthorized access to privileged control-plane endpoints (/live/runner/start, /swarm/runs, /sessions/{id}/messages); credential exfiltration via settings overwrite (/settings/llm, /settings/data-sources)

Impact Parity

  • Disclosed/claimed maximum impact: DNS rebinding authentication bypass leading to remote code execution (code_execution) and credential exfiltration
  • Reproduced impact from this run: Full chain demonstrated — DNS rebinding → auth bypass → shell tools enabled → BashTool executes arbitrary shell command as API process user (uid=1000(vscode)). The proof file /tmp/vibe_trading_rce_proof_*.txt was created with RCE_CONFIRMED. The agent trace shows tool_call: bash with exit_code: 0 and stdout: "uid=1000(vscode)...".
  • Parity: full
  • Not demonstrated: The reproduction used a mock LLM server (simulating an attacker-controlled LLM endpoint) to instruct the agent to invoke the bash tool. In a real attack, the attacker would either poison the LLM settings (via the auth-bypassed /settings/llm PUT) to point the agent at an attacker-controlled LLM, or craft a user message that persuades the agent to run a shell command. The code-execution primitive (BashTool with subprocess.run(shell=True)) is the same either way.

Root Cause

The root cause is a loopback peer IP trust without Host header validation:

  1. _is_local_client(request) (line 668) checks only request.client.host (the TCP peer address). If it is 127.0.0.1, ::1, localhost, or a trusted Docker gateway, it returns True.

  2. _validate_api_auth() (line 645): when API_AUTH_KEY is not configured (dev mode), a loopback client is allowed without any token. When API_AUTH_KEY IS configured, the loopback shortcut is not used — but in dev mode (the default), the bypass is complete.

  3. _shell_tools_enabled_for_request(request) (line 727): returns _is_local_client(request) or _env_shell_tools_enabled(). For loopback clients, this is True, enabling the bash and background_run tools in the agent registry.

  4. No Host header validation existed — a loopback request carrying Host: attacker.example:8899 was trusted as local. DNS rebinding makes a browser send exactly such a request: the attacker's domain resolves to 127.0.0.1, the browser connects from loopback, and sends Host: attacker.example:8899 (the original hostname) with no bearer token.

  5. The BashTool.execute() (line 38 of bash_tool.py) calls subprocess.run(command, shell=True, cwd=cwd, ...) — arbitrary command execution.

Fix (PR #242, commit 6e06017): Added _reject_untrusted_loopback_host middleware that rejects loopback requests carrying an untrusted Host header with HTTP 403 ("Untrusted local API host") before route handlers are reached. Accepted loopback Host values: localhost, 127.0.0.1, ::1, [::1], testserver, plus any configured via API_ALLOWED_HOSTS. Remote clients remain governed by bearer-token auth. Normal loopback dev-mode requests with Host: 127.0.0.1:port continue to work (no regression).

Related fixes in the same v0.1.10 cycle:

  • PR #243 (7eb8dea): require explicit opt-in (VIBE_TRADING_ENABLE_SHELL_TOOLS) for agent shell tools — closes the BashTool exposure even if the Host gate is bypassed
  • PR #245 (b608fc5): require bearer token for settings WRITE endpoints — closes the credential exfiltration path

Reproduction Steps

  1. Script: bundle/repro/reproduction_steps.sh — self-contained, run with PRUVA_ROOT=<bundle_dir> bash bundle/repro/reproduction_steps.sh
  2. What the script does:
    • Installs Python dependencies (fastapi, uvicorn, langchain, dnslib, etc.)
    • Clones/reuses the Vibe-Trading repo from the project cache
    • Starts a DNS rebinding server (dns_rebind_server.py) that resolves rebind.attacker.test to 127.0.0.1
    • Proves the DNS rebinding with a real DNS A-record query → 127.0.0.1
    • Starts a mock OpenAI-compatible LLM server (mock_llm_server.py) that returns a bash tool-call instructing the agent to execute id; whoami; echo RCE_CONFIRMED > /tmp/...
    • Phase 1 (vulnerable v0.1.9): Starts the real Vibe-Trading API server (bound to 0.0.0.0:8899, dev mode, mock LLM). Uses curl --resolve rebind.attacker.test:8899:127.0.0.1 to send DNS-rebound HTTP requests with no bearer token:
      • POST /sessions → HTTP 201 (auth bypassed, session created)
      • POST /sessions/{id}/messages → triggers the agent loop → BashTool executes the attacker's command → RCE proof file created
      • PUT /settings/llm → auth-bypassed settings write (credential exfiltration path)
    • Phase 2 (fixed v0.1.10): Same DNS-rebound requests → HTTP 403 ("Untrusted local API host"). Normal loopback with Host: 127.0.0.1:8899 → HTTP 201 (no regression).
    • Writes validation_verdict.json and runtime_manifest.json
  3. Expected evidence:
    • logs/dns_rebind_proof.txt: DNS_A:rebind.attacker.test:127.0.0.1
    • logs/vuln_create_session.txt: HTTP 201 with session_id (no auth)
    • logs/vuln_rce_proof.txt: RCE_CONFIRMED
    • logs/vuln_trace.jsonl: tool_call: bash with exit_code: 0, stdout: "uid=1000(vscode)..."
    • logs/fixed_create_session.txt: HTTP 403 {"detail":"Untrusted local API host"}
    • logs/fixed_normal_loopback.txt: HTTP 201 (no regression)

Evidence

All artifacts are under bundle/logs/ and bundle/repro/:

Artifact Description
logs/reproduction_steps.log Full script execution log
logs/dns_rebind_proof.txt DNS A-record query proving rebind.attacker.test → 127.0.0.1
logs/vuln_create_session.txt Vulnerable: POST /sessions → HTTP 201 (auth bypass)
logs/vuln_send_message.txt Vulnerable: POST /sessions/{id}/messages → HTTP 200
logs/vuln_rce_proof.txt RCE proof file: RCE_CONFIRMED
logs/vuln_trace.jsonl Agent trace showing tool_call: bash, tool_result: exit_code 0, uid=1000(vscode)
logs/vuln_session_messages.json Session message history (user + assistant reply)
logs/vuln_settings_write.txt Vulnerable: PUT /settings/llm → HTTP 422 (auth bypassed, validation error)
logs/fixed_create_session.txt Fixed: POST /sessions → HTTP 403 "Untrusted local API host"
logs/fixed_normal_loopback.txt Fixed: normal loopback → HTTP 201 (no regression)
logs/fixed_settings_write.txt Fixed: PUT /settings/llm → HTTP 403
logs/api_server_vulnerable.log Vulnerable API server log
logs/api_server_fixed.log Fixed API server log
logs/mock_llm_server.log Mock LLM server log
logs/dns_rebind_server.log DNS rebinding server log

Key trace excerpt (vuln_trace.jsonl):

{"type": "tool_call", "iter": 1, "tool": "bash", "args": {"command": "id; whoami; echo RCE_CONFIRMED > /tmp/vibe_trading_rce_proof_49561.txt", "run_dir": "..."}}
{"type": "tool_result", "iter": 1, "tool": "bash", "status": "ok", "elapsed_ms": 4, "preview": "{\"status\": \"ok\", \"exit_code\": 0, \"stdout\": \"uid=1000(vscode) gid=1000(vscode) groups=1000(vscode),969(969)\\nvscode\\n\", \"stderr\": \"id: cannot find name for group ID 969\\n\"}"}

Vulnerable vs fixed comparison:

Request v0.1.9 (vulnerable) v0.1.10 (fixed)
POST /sessions (DNS-rebound, no auth) 201 (auth bypassed) 403 ("Untrusted local API host")
POST /sessions/{id}/messages (DNS-rebound) 200 → BashTool RCE 403
PUT /settings/llm (DNS-rebound) 422 (auth bypassed) 403
POST /sessions (normal loopback Host: 127.0.0.1) 201 201 (no regression)

Environment:

  • Python 3.14.4, FastAPI + uvicorn, langchain-openai (ChatOpenAI)
  • Vibe-Trading v0.1.9 (vulnerable) / v0.1.10 (fixed)
  • API server bound to 0.0.0.0:8899 (default), dev mode (no API_AUTH_KEY)
  • DNS rebinding server: dnslib UDP server on 127.0.0.1:5353
  • Mock LLM: http.server on 127.0.0.1:9099 returning OpenAI-compatible tool-call responses

Recommendations / Next Steps

  1. Upgrade to v0.1.10 or later — the _reject_untrusted_loopback_host middleware (PR #242) blocks DNS-rebinding Host headers on loopback peers with HTTP 403.
  2. Set API_AUTH_KEY in any deployment exposed beyond a single-user localhost — this forces bearer-token auth even for loopback clients when configured, removing the dev-mode bypass.
  3. Set VIBE_TRADING_ENABLE_SHELL_TOOLS=1 only when explicitly needed — PR #243 requires explicit opt-in for the BashTool; without it, the RCE primitive is unavailable even if auth is bypassed.
  4. Bind to 127.0.0.1 instead of 0.0.0.0 when the API is not meant to be network-accessible.
  5. Configure API_ALLOWED_HOSTS if fronting the local API with a specific loopback hostname.
  6. Testing: run the security regression tests: PYTHONPATH=agent python -m pytest agent/tests/test_security_auth_api.py -q

Additional Notes

  • Idempotency: The script was run twice consecutively; both runs produced identical results (HTTP 201 + RCE on vulnerable, HTTP 403 on fixed). The script cleans up all background processes on exit and uses a PID-suffixed proof file to avoid collisions.
  • Mock LLM justification: The reproduction uses a mock OpenAI-compatible LLM server that returns a bash tool-call. This simulates the attack scenario where the attacker either (a) poisons the LLM settings via the auth-bypassed /settings/llm PUT to point at an attacker-controlled LLM, or (b) sends a user message that the agent's LLM responds to with a bash tool-call. The BashTool's subprocess.run(shell=True) is the actual RCE primitive in both cases — the mock LLM merely drives the agent loop to reach it.
  • The PUT /settings/llm returned 422 (not 200) on the vulnerable version because the request body did not match the full Pydantic model schema, but the important point is that the request passed authentication (no 401/403) — the auth bypass is confirmed. On the fixed version, the same request returns 403 at the Host-gate middleware before reaching the route handler.
  • CORS does not defend against DNS rebinding — after rebinding, the attacker's hostname becomes the browser's same origin, so credentialed CORS requests are sent without cross-origin restrictions.

Variant Analysis & Alternative Triggers for CVE-2026-58169

Versions: versions (as tested):Fixed: target under test: v0.1.10, commit 54f944743efee7b9cbaaeafb5966c583d0d4ac66.

A partial bypass of the v0.1.10 Host-validation fix (PR #242) was confirmed: the production loopback-Host allowlist _DEFAULT_LOOPBACK_HOSTS includes "testserver" — a non-loopback hostname added for Starlette TestClient convenience. A loopback peer request carrying Host: testserver:<port> and no bearer token passes the _reject_untrusted_loopback_host middleware and is auth-bypassed on the fixed v0.1.10 (POST /sessions → HTTP 201), exactly where an attacker-domain Host is correctly rejected (HTTP 403). In the default configuration the independent shell-tools opt-in (PR #243) still blocks the BashTool RCE primitive, so the partial bypass does not yield RCE by default. However, when the operator has enabled VIBE_TRADING_ENABLE_SHELL_TOOLS=1 (the exact scenario the opt-in exists for), the testserver Host bypass restores the full RCE chain on the fixed v0.1.10 — demonstrated end-to-end (Host: testserver → session → agent message → BashTool subprocess.run(shell=True)RCE_CONFIRMED). This is a conditional bypass: in the standard DNS-rebinding model the attacker cannot deliver Host: testserver (they control an attacker-owned domain, not the bare label testserver), so the standard DNS-rebinding RCE bypass is not confirmed. The finding is a genuine incompleteness in the fix's allowlist that should be closed.

Fix Coverage / Assumptions

Invariant the fix relies on (PR #242): a loopback peer may carry only a Host that names a loopback address (or an operator-configured API_ALLOWED_HOSTS name); any other Host on a loopback peer is a DNS-rebinding artifact and is rejected with HTTP 403 before route handlers run.

Code paths explicitly covered: every HTTP request passes through _reject_untrusted_loopback_host (@app.middleware("http"), agent/api_server.py:562). Loopback peers with a Host outside _DEFAULT_LOOPBACK_HOSTS ∪ _EXTRA_LOOPBACK_HOSTS are rejected. Non-loopback peers pass through to per-route _validate_api_auth, which requires API_AUTH_KEY for non-local access. Secondary defenses: PR #243 gates bash/background_run behind VIBE_TRADING_ENABLE_SHELL_TOOLS; PR #245 requires a bearer token for settings writes.

What the fix does NOT cover: the allowlist trusts "testserver", a non-loopback test hostname. This violates the fix's own invariant and lets a loopback peer with Host: testserver be auth-bypassed on the fixed version.

Variant / Alternate Trigger

Variant ID: VT-CVE-2026-58169-testserver-host-allowlist

Entry point: POST /sessions/{id} and POST /sessions/{id}/messages over the Vibe-Trading API (agent/api_server.py), reached by a loopback peer (127.0.0.1) sending Host: testserver:<port> with no Authorization bearer header. curl --resolve testserver:<port>:127.0.0.1 ... reproduces the request shape a victim browser would produce when the victim's resolver maps testserver127.0.0.1.

Code path (fixed v0.1.10):

  1. _reject_untrusted_loopback_host (api_server.py:562): _is_local_client() True; _is_allowed_loopback_host("testserver:18899")_host_without_port"testserver"_DEFAULT_LOOPBACK_HOSTSTrue; middleware passes (no 403).
  2. require_auth_validate_api_auth (api_server.py:760): _is_local_client() True → returns immediately (no auth).
  3. POST /sessions (api_server.py:1801) → HTTP 201, session created.
  4. POST /sessions/{id}/messages (api_server.py:2094) → agent loop.
  5. _shell_tools_enabled_for_request (api_server.py:844): returns _env_shell_tools_enabled(). Default: False (bash disabled). With VIBE_TRADING_ENABLE_SHELL_TOOLS=1: Truebash tool registered.
  6. Mock/attacker LLM returns a bash tool-call → BashTool.execute (agent/src/tools/bash_tool.py) → subprocess.run(command, shell=True) → RCE.

Other candidates tested and ruled out:

  • Attacker-domain Host (rebind.attacker.test): fixed v0.1.10 → 403 (fix works). This is the control, not a bypass.

  • Direct cross-origin fetch to localhost: Host: localhost is allowlisted by design; cross-origin browser requests are CORS-limited (loopback-only origins, no * with credentials), so the session_id cannot be read to drive RCE. Not a bypass.

  • Unauthenticated routes (/health, /api, /skills, /correlation): non-sensitive / read-only; do not reach the auth-bypass or RCE sink.

  • WebSocket / SSE transports: no @app.websocket endpoints; SSE streams go through the Host middleware then _validate_api_auth.

  • Non-shell file tools (write_file, edit_file): not gated by the shell-tools opt-in, so they could overwrite agent/.env once an auth bypass exists — a secondary gap, not an independent bypass.

  • Package/component affected: HKUDS/Vibe-Tradingagent/api_server.py (_DEFAULT_LOOPBACK_HOSTS / _reject_untrusted_loopback_host allowlist), agent/src/tools/bash_tool.py (BashTool RCE primitive), agent/src/tools/__init__.py (_SHELL_TOOL_NAMES gating).

  • Affected versions (as tested):

    • Vulnerable baseline: v0.1.9, commit 8cebccb9b301f962d11bf0fa8c6be9bf7d7e12f2.
    • Fixed target under test: v0.1.10, commit 54f944743efee7b9cbaaeafb5966c583d0d4ac66.
  • Risk level: High for the conditional full-bypass scenario (opted-in shell tools + testserver resolves to loopback): unauthenticated RCE as the API process user. Medium for the default-config partial bypass: unauthenticated session creation / control-plane access without RCE.

  • Consequences: unauthenticated session creation and agent control on the fixed version via Host: testserver; full RCE when shell tools are opted in.

Impact Parity

  • Disclosed/claimed maximum impact (parent CVE): DNS rebinding → authentication bypass → remote code execution (code_execution) and credential exfiltration.
  • Reproduced impact from this variant run:
    • Auth bypass on fixed v0.1.10 via Host: testserver → HTTP 201 (confirmed).
    • Full RCE on fixed v0.1.10 only in the opted-in shell-tools config (VIBE_TRADING_ENABLE_SHELL_TOOLS=1): BashTool executed id; whoami; echo RCE_CONFIRMED > /tmp/...; proof file written (RCE_CONFIRMED); run state.json = {"status":"success"}.
    • In the default fixed config, the auth bypass does not escalate to RCE (bash gated by PR #243).
  • Parity: partial. The auth-bypass half of the CVE is reproduced on the fixed version; the RCE half is reproduced only under the non-default opted-in-shell-tools condition, and the standard DNS-rebinding delivery of Host: testserver is not confirmed.
  • Not demonstrated: a fully unattended, standard-DNS-rebinding RCE bypass on the fixed version (the attacker cannot deliver Host: testserver from an attacker-owned domain), and credential exfiltration via settings writes on the fixed version (PR #245 blocks it).

Root Cause

The same underlying bug — loopback peer-IP trust accepted without a sufficiently strict Host validation — is still reachable because the fix's allowlist (_DEFAULT_LOOPBACK_HOSTS) over-trusts a non-loopback name, "testserver". The fix's middleware correctly rejects attacker-domain Hosts, but the allowlist membership test normalized in _DEFAULT_LOOPBACK_HOSTS returns True for testserver, so a loopback peer bearing that Host is treated as a trusted local caller and skips _validate_api_auth. The BashTool sink (subprocess.run(shell=True)) is then reachable when shell tools are opted in.

Fix commit (the Host middleware): PR #242, commit 6e06017 (6e06017... in v0.1.9..v0.1.10). The gap lives in the _DEFAULT_LOOPBACK_HOSTS frozenset at agent/api_server.py:483.

Reproduction Steps

  1. Script: bundle/vuln_variant/reproduction_steps.sh — self-contained. Run with PRUVA_ROOT=<bundle_dir> bash bundle/vuln_variant/reproduction_steps.sh.
  2. What the script does:
    • Ensures Python deps; creates/uses isolated git worktrees (bundle/artifacts/vt-vuln @ v0.1.9, bundle/artifacts/vt-fixed @ v0.1.10) so the repro cache clone is not mutated.
    • Starts a mock OpenAI-compatible LLM that returns a bash tool-call.
    • Phase 1 (v0.1.9 baseline): for Hosts rebind.attacker.test, testserver, localhostPOST /sessions (all 201, no Host check); full RCE chain via attacker Host (control).
    • Phase 2 (v0.1.10 default): attacker Host → 403 (fix works); testserver Host → 201 (partial bypass); localhost → 201 (baseline); testserver + message → no RCE (bash gated by opt-in).
    • Phase 3 (v0.1.10 opted-in, VIBE_TRADING_ENABLE_SHELL_TOOLS=1): attacker Host → 403 (Host middleware still blocks DNS rebinding); testserver Host → 201 → message → BashTool RCE CONFIRMED.
    • Logs every attempt; exits 1 (no standard DNS-rebinding RCE bypass) but records the partial/conditional bypass.
  3. Expected evidence:
    • logs/vuln_variant/fixed_default_host_testserver.txt → HTTP 201 (auth bypass on fixed).
    • logs/vuln_variant/fixed_default_host_rebind.attacker.test.txt → HTTP 403 (fix blocks standard DNS rebinding).
    • logs/vuln_variant/fixed_optedin_host_testserver.txt → HTTP 201.
    • logs/vuln_variant/fixed_optedin_ts_rce_proof.txtRCE_CONFIRMED (full chain on fixed, opted-in config).
    • logs/vuln_variant/fixed_optedin_ts_state.json{"status":"success"}.
    • logs/vuln_variant/vuln_rce_proof.txtRCE_CONFIRMED (v0.1.9 control).

Evidence

All artifacts under bundle/logs/vuln_variant/ and bundle/vuln_variant/:

Artifact Description
logs/vuln_variant/variant_steps.log Full script execution log (both runs).
logs/vuln_variant/vuln_host_{attacker,testserver,localhost}.txt v0.1.9: all Hosts → 201 (no Host check).
logs/vuln_variant/vuln_rce_proof.txt v0.1.9 control RCE: RCE_CONFIRMED.
logs/vuln_variant/fixed_default_host_rebind.attacker.test.txt Fixed default: attacker Host → 403.
logs/vuln_variant/fixed_default_host_testserver.txt Fixed default: testserver Host → 201 (partial bypass).
logs/vuln_variant/fixed_default_host_localhost.txt Fixed default: localhost → 201 (baseline).
logs/vuln_variant/fixed_default_ts_msg.txt Fixed default: testserver message → no RCE (bash gated).
logs/vuln_variant/fixed_optedin_host_rebind.attacker.test.txt Fixed opted-in: attacker Host → 403.
logs/vuln_variant/fixed_optedin_host_testserver.txt Fixed opted-in: testserver Host → 201.
logs/vuln_variant/fixed_optedin_ts_msg.txt Fixed opted-in: testserver message → triggers bash.
logs/vuln_variant/fixed_optedin_ts_rce_proof.txt Fixed opted-in: RCE_CONFIRMED (full chain on fixed).
logs/vuln_variant/fixed_optedin_ts_state.json Run state: {"status":"success"}.
logs/vuln_variant/api_server_{vuln,fixed-default,fixed-optedin}.log API server logs per phase.
vuln_variant/mock_llm_server.py Mock OpenAI LLM returning a bash tool-call.
vuln_variant/reproduction_steps.sh Variant reproduction script.

Key excerpt — fixed v0.1.10 default, testserver Host:

Host=testserver
HTTP 201
{"session_id":"0d6dac8dad41","title":"","status":"active",...}

Key excerpt — fixed v0.1.10 default, attacker Host (control):

Host=rebind.attacker.test
HTTP 403
{"detail":"Untrusted local API host"}

Key excerpt — fixed v0.1.10 opted-in RCE:

[08:29:23]   *** fixed-optedin testserver RCE CONFIRMED: RCE_CONFIRMED ***
state.json: {"status":"success"}

Environment: Python 3.14.4, FastAPI + uvicorn, langchain-openai; isolated git worktrees at v0.1.9 (8cebccb) and v0.1.10 (54f9447); API bound to 0.0.0.0:18899 (dev mode, no API_AUTH_KEY); mock LLM on 127.0.0.1:19099.

Recommendations / Next Steps

  1. Remove testserver from the production allowlist. Move it to a test-only override (e.g. an env flag VIBE_TRADING_TEST_HOSTS consulted only when testing, or inject it in conftest.py via API_ALLOWED_HOSTS for the TestClient). Production _DEFAULT_LOOPBACK_HOSTS should contain only genuine loopback names: localhost, 127.0.0.1, ::1, [::1]. This closes the partial bypass with no production behavior change (no real client sends Host: testserver).
  2. Tighten the allowlist semantics. Consider validating that the Host, after port stripping, resolves to a loopback address (or is an explicit operator entry) rather than trusting fixed bare labels — defense in depth against future allowlist drift.
  3. Gate file-mutating agent tools (write_file, edit_file, skill_writer) behind the same VIBE_TRADING_ENABLE_SHELL_TOOLS opt-in (or a separate VIBE_TRADING_ENABLE_FILE_TOOLS), so an auth-bypassed agent cannot overwrite agent/.env to redirect credentials, bypassing PR #245's settings-write gate.
  4. Keep the shell-tools opt-in default-off (PR #243) — it correctly prevents the testserver partial bypass from escalating to RCE in the default configuration. Document that operators who enable shell tools must not expose the API to environments where testserver resolves to loopback.
  5. Bind defaults: consider changing the default --host from 0.0.0.0 to 127.0.0.1 so a fresh dev deployment is not network-reachable by default.

Additional Notes

  • Idempotency: the script was run twice; both runs completed without crashing and produced identical verdicts (exit 1; partial auth-bypass = yes; opted-in RCE = yes; standard DNS-rebinding bypass = no). It reuses existing worktrees, frees ports between phases, and cleans up on exit.
  • No repo state mutation: the repro cache clone (/data/pruva/project-cache/.../repo) remained at v0.1.10 (54f9447) throughout; all version switching used isolated git worktrees under bundle/artifacts/.
  • Honest scope: this is reported as a partial/conditional bypass, not a confirmed standard DNS-rebinding RCE bypass, because Host: testserver is not deliverable from an attacker-owned domain via normal DNS rebinding. The finding is nonetheless a real fix-completeness defect (an over-broad production allowlist) that restores the full chain under a realistic operator-opted-in configuration.

CVE-2026-58169 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:001:01
0:00
session startedaccounts/fireworks/routers/glm-5p2-fast · CVE-2026-58169 · REPRO-20
0:02
0:05
web search
0:07
web search
0:09
0:11
web search
0:13
web search
0:16
0:17
0:18
0:39
0:39
extract_facts
no facts extracted
0:41
0:41
0:41
supportrepro
0:43
0:43
0:43
0:44
0:44
0:44
0:47
0:47
0:48
web search
0:51
0:51
0:52
0:56
0:59
$cd /data/pruva/project-cache/b9cd83d4-18cf-44e8-8cea-3367d315f18e && git clone --quiet https://github.com/HKUDS/Vibe-Trading.git repo 2>&1 | tail -5; echo "EXIT: $?"; ls repo 2>/dev/null | head
2.5s
EXIT: 0
AGENT_CONTRIBUTOR_GUIDE.md
CHANGELOG.md
CODE_OF_CONDUCT.md
CONTRIBUTING.md
Dockerfile
LICENSE
MANIFEST.in
1:01

Artifacts and Evidence for CVE-2026-58169

Scripts, logs, diffs, and output captured during the reproduction.

bundle/artifact_promotion_manifest.json17.9 KB
bundle/vuln_variant/source_identity.json1.5 KB
bundle/vuln_variant/root_cause_equivalence.json3.0 KB
bundle/logs/vuln_rce_proof.txt0.0 KB
bundle/logs/vuln_trace.jsonl1.0 KB
bundle/logs/dns_rebind_proof.txt0.0 KB
bundle/repro/reproduction_steps.sh15.7 KB
bundle/repro/rca_report.md12.0 KB
bundle/repro/validation_verdict.json1.0 KB
bundle/repro/runtime_manifest.json1.2 KB
bundle/logs/fixed_create_session.txt0.0 KB
bundle/logs/vuln_create_session.txt0.2 KB
bundle/logs/reproduction_steps.log3.1 KB
bundle/logs/vuln_send_message.txt0.1 KB
bundle/logs/vuln_session_messages.json0.5 KB
bundle/logs/vuln_settings_write.txt0.2 KB
bundle/logs/fixed_normal_loopback.txt0.2 KB
bundle/logs/fixed_settings_write.txt0.0 KB
bundle/logs/api_server_vulnerable.log1.1 KB
bundle/logs/api_server_fixed.log0.8 KB
bundle/logs/mock_llm_server.log0.1 KB
bundle/logs/dns_rebind_server.log0.1 KB
bundle/vuln_variant/reproduction_steps.sh14.4 KB
bundle/logs/vuln_variant/fixed_optedin_ts_rce_proof.txt0.0 KB
bundle/logs/vuln_variant/fixed_default_host_testserver.txt0.2 KB
bundle/logs/vuln_variant/fixed_default_host_rebind.attacker.test.txt0.1 KB
bundle/logs/vuln_variant/variant_steps.log2.9 KB
bundle/vuln_variant/variant_manifest.json4.4 KB
bundle/vuln_variant/validation_verdict.json3.6 KB
bundle/vuln_variant/patch_analysis.md11.2 KB
bundle/vuln_variant/rca_report.md14.3 KB
bundle/vuln_variant/runtime_manifest.json3.6 KB
bundle/logs/vuln_variant/vuln_host_rebind.attacker.test.txt0.2 KB
bundle/logs/vuln_variant/vuln_host_testserver.txt0.2 KB
bundle/logs/vuln_variant/vuln_host_localhost.txt0.2 KB
bundle/logs/vuln_variant/vuln_rce_proof.txt0.0 KB
bundle/logs/vuln_variant/fixed_default_host_localhost.txt0.2 KB
bundle/logs/vuln_variant/fixed_default_ts_msg.txt0.1 KB
bundle/logs/vuln_variant/fixed_optedin_host_rebind.attacker.test.txt0.1 KB
bundle/logs/vuln_variant/fixed_optedin_host_testserver.txt0.2 KB
bundle/logs/vuln_variant/fixed_optedin_ts_msg.txt0.1 KB
bundle/logs/vuln_variant/fixed_optedin_ts_state.json0.0 KB
bundle/logs/vuln_variant/fixed_optedin_ts_req.json0.1 KB
bundle/logs/vuln_variant/api_server_vuln.log1.1 KB
bundle/logs/vuln_variant/api_server_fixed-default.log2.5 KB
bundle/logs/vuln_variant/api_server_fixed-optedin.log2.5 KB
bundle/logs/vuln_variant/mock_llm_server.log0.0 KB
08 · How to Fix

How to Fix CVE-2026-58169

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-58169 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-58169

How does the CVE-2026-58169 exploit chain reach RCE?

Once the DNS-rebinding request lands as a trusted loopback client, _shell_tools_enabled_for_request() also returns True for loopback clients, enabling the agent's bash tool. The attacker sends a message to a session that triggers BashTool, which runs subprocess.run(command, shell=True), giving remote code execution as the API process user; the attacker can also overwrite LLM and data-source settings to exfiltrate credentials.

Which Vibe-Trading versions are affected by CVE-2026-58169, and where is it fixed?

Vibe-Trading versions before 0.1.10 are affected (confirmed on v0.1.9). It is fixed in 0.1.10.

How severe is CVE-2026-58169?

It is rated high severity: an unauthenticated attacker who can lure a victim to a malicious page can bypass authentication via DNS rebinding and achieve remote code execution as the API process user.

How can I reproduce CVE-2026-58169?

Download the verified script from this page and run it in an isolated environment against Vibe-Trading before 0.1.10. It sets up a DNS rebinding scenario targeting the FastAPI server, sends requests that satisfy the loopback-trust check without a bearer token, and then invokes the bash tool to demonstrate command execution on the vulnerable build.
11 · References

References for CVE-2026-58169

Authoritative sources for CVE-2026-58169 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.