CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-WF6J-7HVR-GR93

GHSA-wf6j-7hvr-gr93: Arbitrary Code Execution via PyYAML Target Blocklist Bypass in hydra-core

Alon Barad
Alon Barad
Software Engineer

Oct 27, 2026·10 min read·1 visit

Executive Summary (TL;DR)

Hydra's dynamic object instantiation blocklist omitted the PyYAML namespace (yaml.), enabling attackers who control configuration metadata passed to hydra.utils.instantiate() or hydra.utils.call() to invoke yaml.unsafe_load and achieve arbitrary code execution.

A high-severity target blocklist omission in the hydra-core Python package (versions 1.3.6 through 1.3.7 and 1.4.0.dev9 through 1.4.0rc2) allows arbitrary code execution when instantiating untrusted configuration dictionaries. Because the execution policy failed to restrict the PyYAML (yaml.) namespace, an attacker can specify functions such as yaml.unsafe_load as the instantiation target and supply a crafted YAML stream containing Python object construction tags to execute arbitrary system commands within the host process.

Vulnerability Overview

Hydra is an open-source Python framework developed by Meta and maintained by the Hydra Ecosystem for managing complex, hierarchical application configurations. A core feature of the framework is dynamic object creation via the hydra.utils.instantiate() and hydra.utils.call() functions. These utilities accept configuration dictionaries or OmegaConf objects, inspect the _target_ key to locate an importable Python callable (such as a class constructor or function), and invoke that callable using the remaining keys in the dictionary as keyword arguments.

In machine learning and data science pipelines, applications frequently load model configurations from external repositories, checkpoints, or third-party hubs and pass them directly to instantiate(). To prevent untrusted configuration files from invoking arbitrary system commands during instantiation, Hydra introduced an execution policy mechanism in versions 1.3.6 and 1.4.0.dev9 (following earlier disclosures tracked as GHSA-2cp2-2r3c-7p7r and GHSA-rqx7-p7vv-w7hr). When an explicit allowlist is not provided by the developer, Hydra falls back to a default target policy that enforces a prefix blocklist against known dangerous Python modules and builtins.

GHSA-wf6j-7hvr-gr93 (also tracked internally by the repository as GHSA-757g-8w3h-hp29) is an Incomplete List of Disallowed Inputs (CWE-184) and Deserialization of Untrusted Data (CWE-502) vulnerability within this target blocklist. The blocklist implementation in hydra/_internal/execution_policy.py and hydra/_internal/target_policy.py restricted standard library serialization and debugging modules such as pickle., shelve., pdb., and pydoc., but completely omitted the yaml. namespace provided by PyYAML.

Because hydra-core depends on OmegaConf, which in turn requires PyYAML as a core dependency, the yaml module is guaranteed to be present in any standard Hydra runtime environment. Consequently, an attacker who controls the configuration dictionary passed to instantiate() or call() can specify _target_: yaml.unsafe_load along with a malicious YAML string, bypassing the execution policy and achieving arbitrary code execution (CWE-94) within the context of the Python process.

Root Cause Analysis

The root cause of GHSA-wf6j-7hvr-gr93 lies in the architectural limitations of using a denylist to restrict dynamic symbol resolution in Python, specifically the omission of the yaml. module prefix from Hydra's uncontrolled execution target prefix tuple. When hydra.utils.instantiate() processes a configuration node, it resolves the string specified in _target_ into a live Python callable and validates its canonical path against the policy rules defined in execution_policy.py (in the 1.4 branch) or target_policy.py (in the 1.3 branch).

The validation logic checks two primary structures: an exact match set of prohibited callables (UNCONTROLLED_EXECUTION_TARGETS, which blocks functions like eval, exec, os.system, and subprocess.Popen) and a tuple of prohibited module prefixes (UNCONTROLLED_EXECUTION_TARGET_PREFIXES). If a target matches a prohibited prefix, Hydra blocks instantiation unless the exact target path is explicitly listed in UNCONTROLLED_EXECUTION_TARGET_PREFIX_EXCEPTIONS.

While the policy blocked direct invocation of os.system and pickle.loads, it permitted calls to any function inside the yaml package. PyYAML provides multiple loading functions, including yaml.unsafe_load(), yaml.unsafe_load_all(), yaml.load(), and yaml.full_load(), as well as direct loader classes like yaml.UnsafeLoader and yaml.Loader. Unlike yaml.safe_load(), which restricts deserialization to standard YAML primitives, yaml.unsafe_load() permits arbitrary Python object instantiation via specialized YAML tags.

Specifically, PyYAML supports the !!python/object/apply:<module>.<callable> tag. When yaml.unsafe_load() parses a stream containing this tag, PyYAML's internal constructor (UnsafeConstructor.construct_python_object_apply) imports the specified module, resolves the callable, and executes it with the arguments provided in the YAML sequence or mapping. Because this secondary resolution and execution occur entirely inside PyYAML's C or Python runtime after Hydra has already approved and invoked yaml.unsafe_load, Hydra's target policy is never consulted for the inner callable. PyYAML effectively acts as an unrestricted execution proxy.

Code Analysis

The vulnerability was remediated across two branches: commit 9a7a9a287d565311183da3392bee4345a7fab6d7 on the main (1.4 prerelease) branch and commit de5554320c17cd2d974492c03d0b1456adb4a8ef on the 1.3 stable branch. In both commits, the maintainers updated the prefix blocklist to deny the entire yaml. namespace while carving out explicit exceptions for the four stateless, safe serialization helpers.

In hydra/_internal/execution_policy.py (and identically in hydra/_internal/target_policy.py), the UNCONTROLLED_EXECUTION_TARGET_PREFIXES tuple and UNCONTROLLED_EXECUTION_TARGET_PREFIX_EXCEPTIONS frozenset were modified as follows:

--- a/hydra/_internal/execution_policy.py
+++ b/hydra/_internal/execution_policy.py
@@ -356,6 +356,9 @@
     # unpickles a counts file. The inert Trace constructor is excepted below.
     "shelve.",
     "trace.",
+    # PyYAML exposes Python-object loading and constructor dispatch. Keep only
+    # exact safe load/dump functions available.
+    "yaml.",
     # pydoc imports/executes modules and files (importfile runs a file,
     # safeimport imports by name). Inert documentation formatters are excepted
     # below.
@@ -367,7 +370,7 @@
     "bdb.",
 )
 
-# Exact legitimate constructors within otherwise denied module families. Exact
+# Exact legitimate targets within otherwise denied module families. Exact
 # entries in UNCONTROLLED_EXECUTION_TARGETS still take precedence over exceptions.
 # An exception permits only the named target, not its methods or descendants.
 UNCONTROLLED_EXECUTION_TARGET_PREFIX_EXCEPTIONS = frozenset(
@@ -378,6 +381,10 @@
         "pydoc.HTMLDoc",
         "pydoc.TextDoc",
         "trace.Trace",
+        "yaml.safe_load",
+        "yaml.safe_load_all",
+        "yaml.safe_dump",
+        "yaml.safe_dump_all",
     }
 )

By blocking the yaml. prefix rather than attempting to enumerate individual functions like yaml.unsafe_load, the patch also prevents attackers from instantiating internal PyYAML classes such as yaml.UnsafeLoader, yaml.FullLoader, yaml.constructor.UnsafeConstructor, or invoking yaml.load with a custom Loader argument. Furthermore, because Hydra resolves callables to their canonical module and qualified name (__module__ and __qualname__) prior to policy evaluation, importing yaml.unsafe_load as an alias in another module is also caught and blocked.

To prevent runtime monkey-patching or accidental modification of the security policy structures, Hydra enforces a hardcoded SHA-256 integrity check over the policy definitions. In commit 9a7a9a287d565311183da3392bee4345a7fab6d7, the expected policy digest in hydra/_internal/instantiate/_instantiate2.py and hydra/_internal/logging_config.py was updated to reflect the addition of the yaml. rules:

# Updated SHA-256 digest in _instantiate2.py and logging_config.py (1.4 branch)
_EXPECTED_EXECUTION_POLICY_DIGEST = "208a0d1fdfebeb40610a31c5aff0373b690af5cbcc1bb1cf3c83cfd8bf3ccf41"
 
# Updated SHA-256 digest in target_policy.py (1.3 branch)
_EXPECTED_TARGET_POLICY_DIGEST = "73bf7f617a627fa54bc01889ed4d923471c4b5e39fbd40e119d7f0d485c8a36b"

> [!NOTE] > While this patch closes the PyYAML vector, the maintainers explicitly note in the documentation and test suites that denylisting is a defense-in-depth measure rather than a complete sandbox. Any third-party library installed in the same Python environment that exposes dangerous deserialization or evaluation primitives not present on Hydra's blocklist could reintroduce a similar bypass unless strict whitelisting (_execution_whitelist_) is enforced.

Exploitation

Exploiting GHSA-wf6j-7hvr-gr93 requires an application to pass attacker-controlled configuration data into hydra.utils.instantiate() or hydra.utils.call() without specifying a restrictive _execution_whitelist_. In practice, this attack surface is prevalent in artificial intelligence and machine learning workflows. Frameworks built on Hydra often load architecture definitions, tokenizer settings, or preprocessing pipelines from YAML files bundled inside downloaded model checkpoints (e.g., from Hugging Face Hub or ModelScope).

To construct a working exploit, the attacker defines a configuration dictionary containing _target_: "yaml.unsafe_load" and supplies the stream argument required by yaml.unsafe_load(stream, Loader=...). The stream value is a string formatted with the PyYAML !!python/object/apply tag pointing to a standard library function such as os.system, os.mkdir, or subprocess.Popen.

from hydra.utils import instantiate
 
# Malicious configuration dictionary simulating an untrusted YAML config
malicious_config = {
    "_target_": "yaml.unsafe_load",
    "stream": "!!python/object/apply:os.system ['id > /tmp/hydra_poc.txt']"
}
 
# In hydra-core 1.3.6 - 1.3.7 and 1.4.0.dev9 - 1.4.0rc2,
# this call bypasses the target policy and executes the shell command.
instantiate(malicious_config)

An alternative exploitation path involves invoking yaml.unsafe_load_all, which returns a Python generator object rather than executing the YAML stream immediately upon invocation. However, if the surrounding application iterates over the instantiated object (for example, expecting a list or iterable of layers or callbacks), iterating the generator triggers the lazy evaluation of the YAML stream and executes the embedded payload.

import sys
import yaml
from hydra.utils import instantiate
 
# Even if an application aliases the function, canonical resolution is bypassed
# in unpatched versions and blocked in patched versions.
sys.modules[__name__].aliased_loader = yaml.unsafe_load
 
config = {
    "_target_": f"{__name__}.aliased_loader",
    "stream": "!!python/object/apply:os.mkdir ['/tmp/alias_executed']"
}
 
instantiate(config)

In patched versions (1.3.8 and 1.4.0rc3), executing either of the above snippets raises an InstantiationException wrapping a TargetPolicyError (or ExecutionPolicyError), halting execution before yaml.unsafe_load is invoked.

Impact Assessment

The vulnerability is rated High severity with a CVSS v3.1 base score of 7.8 (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H). The Attack Vector is classified as Local (AV:L) with User Interaction Required (UI:R) because standard exploitation relies on a user or automated pipeline downloading and loading an untrusted configuration file or model bundle. However, if a web service or inference API exposes an endpoint that accepts user-supplied JSON or YAML parameters and passes them directly to hydra.utils.instantiate(), the vulnerability can be triggered remotely over the network without authentication.

Successful exploitation grants the attacker arbitrary code execution with the full privileges of the Python runtime process. This results in a complete compromise of Confidentiality (C:H), Integrity (I:H), and Availability (A:H) within the scope of that process (S:U).

In typical ML training and inference environments, Python processes run with access to high-value assets. An attacker achieving code execution in these environments can exfiltrate cloud provider credentials (such as AWS IAM roles or GCP service account tokens), steal proprietary model weights and training datasets, extract API keys for services like Hugging Face or Weights & Biases from environment variables, or deploy persistent backdoors onto GPU compute clusters.

Because GHSA-wf6j-7hvr-gr93 is tracked natively as a GitHub Security Advisory without an assigned CVE identifier, it does not have an EPSS score and is not eligible for inclusion in the CISA Known Exploited Vulnerabilities (KEV) catalog. Nevertheless, functional proof-of-concept payloads are publicly documented in the official Hydra test suite and security advisory.

Remediation

Development and operations teams utilizing hydra-core should immediately upgrade to the patched releases published on October 27, 2026. Users on the stable 1.3 release train must upgrade to version 1.3.8 or later, while users testing the 1.4 prerelease branch must upgrade to 1.4.0rc3 or later.

# Upgrade stable 1.3 branch
pip install --upgrade "hydra-core>=1.3.8"
 
# Upgrade 1.4 prerelease branch
pip install --upgrade "hydra-core>=1.4.0rc3"

Beyond applying the package update, software engineers must treat dynamic instantiation of external configurations as an inherently privileged operation. As demonstrated by the progression of blocklist bypasses (GHSA-2cp2-2r3c-7p7r, GHSA-rqx7-p7vv-w7hr, and GHSA-wf6j-7hvr-gr93), relying solely on a default module denylist does not provide a guaranteed security boundary against arbitrary third-party packages installed in the Python environment.

When loading configuration files from untrusted or semi-trusted sources in Hydra 1.4, developers should enforce strict allowlisting by passing the _execution_whitelist_ parameter to instantiate() or call(). This parameter restricts instantiation exclusively to the exact target names specified in the allowlist.

from hydra.utils import instantiate
 
# Define an explicit allowlist of trusted application targets in code
TRUSTED_TARGETS = (
    "my_app.models.TransformerEncoder",
    "my_app.optimizers.AdamW",
    "yaml.safe_load",
)
 
# Any _target_ not explicitly in TRUSTED_TARGETS will be rejected
model = instantiate(untrusted_cfg, _execution_whitelist_=TRUSTED_TARGETS)

> [!IMPORTANT] > Never populate _execution_whitelist_ from values contained within the external configuration file itself, and never enable the UNSAFE_DISABLE_EXECUTION_CHECKS environment variable or flag in production environments processing external data.

Official Patches

Hydra EcosystemHydra v1.3.8 Release
Hydra EcosystemHydra v1.4.0rc3 Release

Fix Analysis (2)

Technical Appendix

CVSS Score
7.8/ 10
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Affected Systems

hydra-core (PyPI)

Affected Versions Detail

Product
Affected Versions
Fixed Version
hydra-core
Hydra Ecosystem
>= 1.3.6, < 1.3.81.3.8
hydra-core
Hydra Ecosystem
>= 1.4.0.dev9, < 1.4.0rc31.4.0rc3
AttributeDetail
Advisory IDGHSA-wf6j-7hvr-gr93 (GHSA-757g-8w3h-hp29)
Primary CWECWE-184 (Incomplete List of Disallowed Inputs)
Secondary CWECWE-502 (Deserialization of Untrusted Data)
CVSS v3.1 Score7.8 High (AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)
Attack VectorLocal / Untrusted Configuration Instantiation
ImpactArbitrary Code Execution
Exploit StatusProof-of-Concept Available
Patched Versionshydra-core 1.3.8, 1.4.0rc3

MITRE ATT&CK Mapping

T1059.006Command and Scripting Interpreter: Python
Execution
T1203Exploitation for Client Execution
Execution
T1195.002Supply Chain Compromise: Compromise Software Supply Chain
Initial Access
CWE-184
Incomplete List of Disallowed Inputs

The product implements a protection mechanism that relies on a list of inputs (or properties of inputs) that are not allowed by policy or otherwise require other action to neutralize before additional processing takes place, but the list is incomplete.

Known Exploits & Detection

GitHub Security AdvisoryOfficial advisory and regression test cases demonstrating arbitrary code execution via _target_: yaml.unsafe_load.

Vulnerability Timeline

Maintainer Omry Yadan commits patches to the main (1.4) and 1.3 branches restricting the yaml.* namespace.
2026-10-25
GitHub Security Advisory GHSA-wf6j-7hvr-gr93 (and repository advisory GHSA-757g-8w3h-hp29) published.
2026-10-27
Patched releases v1.3.8 and v1.4.0rc3 published to GitHub and PyPI.
2026-10-27

References & Sources

  • [1]GitHub Security Advisory GHSA-wf6j-7hvr-gr93
  • [2]Hydra Repository Security Advisory GHSA-757g-8w3h-hp29
  • [3]Fix Commit on 1.4 Branch (9a7a9a287d565311183da3392bee4345a7fab6d7)
  • [4]Fix Commit on 1.3 Branch (de5554320c17cd2d974492c03d0b1456adb4a8ef)
  • [5]Hydra Release v1.3.8
  • [6]Hydra Release v1.4.0rc3
  • [7]Hydra Ecosystem GitHub Repository

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 2 hours ago•CVE-2026-110816
5.3

CVE-2026-110816: Denial of Service via Uncaught Exception in Node.js qs Library

CVE-2026-110816 (GHSA-6pq8-jhm2-2vcw) is an uncaught exception and improper type conversion vulnerability in the Node.js query string parsing and serialization library qs. When invoking qs.stringify with the option arrayFormat set to 'comma', the library fails to safely handle array elements that cannot be coerced into primitive strings, such as objects with a non-callable toString property or null-prototype objects. An unauthenticated remote attacker can supply crafted input via JSON bodies or URL query parameters that, when re-serialized by the application, throws a synchronous TypeError, resulting in HTTP 500 errors or complete Node.js process termination.

Alon Barad
Alon Barad
5 views•10 min read
•about 3 hours ago•CVE-2026-114620
5.4

CVE-2026-114620: Server-Side Request Forgery in Authlib RFC 9101 JWT-Secured Authorization Request

Authlib versions prior to 1.9.0 contain a Server-Side Request Forgery (SSRF) vulnerability in the RFC 9101 JWT-Secured Authorization Request (JAR) server implementation. The JWTAuthenticationRequest class passes an unauthenticated, client-controlled request_uri parameter directly to the abstract get_request_object() method before applying any destination validation or client registration policies. Because the official documentation previously recommended implementing this hook as an unrestricted HTTP fetch, deployments following those guidelines allow remote attackers possessing a valid public client_id to trigger outbound network requests to internal services and infer fetch outcomes via error response variations.

Amit Schendel
Amit Schendel
4 views•11 min read
•about 4 hours ago•GHSA-J456-XH4H-CPF2
7.0

CVE-2026-109956: Path Traversal and Sandbox Bypass in NLTK WekaClassifier

CVE-2026-109956 (GHSA-j456-xh4h-cpf2) is a path traversal vulnerability and security sandbox bypass in the Python Natural Language Toolkit (NLTK) versions 3.10.3 and earlier. The WekaClassifier module fails to validate caller-controlled model file paths before passing them to the Weka Java Virtual Machine (JVM) via command-line arguments. When operating under the nltk.pathsec security sandbox, this omission permits attackers who control model path parameters to read, probe, or overwrite arbitrary files outside authorized NLTK data directories.

Alon Barad
Alon Barad
7 views•10 min read
•about 5 hours ago•CVE-2026-35002
9.8

CVE-2026-35002: Eval Injection and Arbitrary Code Execution in Agno Agent Platform

CVE-2026-35002 is an arbitrary code execution vulnerability in the Agno agent platform (formerly Phidata) affecting all versions prior to 2.3.24. The flaw resides in the model execution logic (libs/agno/agno/models/base.py) and tool serialization logic (libs/agno/agno/tools/function.py), where the application directly passes the field_type string parameter into Python's built-in eval() function to resolve string type names into Python data types. An attacker who can influence FunctionCall arguments via prompt injection or supply untrusted dictionary structures for deserialization can execute arbitrary Python expressions within the context of the host process.

Amit Schendel
Amit Schendel
4 views•9 min read
•3 days ago•CVE-2026-115895
8.8

CVE-2026-115895: Code Injection via Unsanitized Import Alias in Happy DOM ECMAScript Module Compiler

CVE-2026-115895 is a high-severity code injection vulnerability (CWE-94) in the happy-dom npm package prior to version 21.0.4. The vulnerability exists within the ECMAScriptModuleCompiler component, which transforms ECMAScript module syntax into executable Node.js functions when JavaScript evaluation is enabled. Due to an incomplete fix for CVE-2026-33943, the compiler failed to validate local named import aliases against legal JavaScript identifier rules. Attackers supplying crafted module imports—specifically utilizing destructuring default initializers alongside JSON module attributes—can inject arbitrary JavaScript expressions directly into the host Node.js runtime context.

Amit Schendel
Amit Schendel
11 views•10 min read
•3 days ago•CVE-2026-115883
6.0

CVE-2026-115883: Cross-Namespace Access via Dot-Delimited Labels in LangGraph Postgres and SQLite Stores

An improper input validation and authorization bypass vulnerability exists in the LangGraph storage layer affecting langgraph, langgraph-checkpoint-postgres, and langgraph-checkpoint-sqlite. Because relational store implementations serialize namespace tuples into dot-delimited strings without validating labels on read, search, delete, and batch operations, an attacker who controls a namespace label can inject periods (.) to traverse namespace boundaries and access, modify, or delete data belonging to other namespaces.

Amit Schendel
Amit Schendel
9 views•9 min read