Sep 16, 2026·6 min read·5 visits
A mass-assignment vulnerability in djust allows authenticated clients to modify arbitrary public server-side view attributes via crafted WebSocket payloads.
CVE-2026-61598 is a high-severity mass-assignment vulnerability (CWE-915) affecting the Python package djust prior to version 1.0.7. An authenticated client can supply arbitrary parameter names to modify public view attributes on the server via WebSocket events, leading to unauthorized state manipulation, authorization bypass, or price tampering.
The Python package djust is a reactive web framework designed to provide server-side rendering for Django applications. It implements a model binding mechanism over WebSockets to allow real-time synchronization between client-side input elements and server-side state. This functionality is exposed via the ModelBindingMixin class, which is included in the base Method Resolution Order (MRO) of LiveView instances.
CVE-2026-61598 describes a mass-assignment vulnerability within this binding mechanism. The framework permits authenticated clients to invoke the default update_model WebSocket event handler. Under vulnerable versions, arbitrary server-side view attributes can be manipulated if they are public and not protected by an explicit configuration.
The vulnerability is classified under CWE-915 (Improperly Controlled Modification of Dynamically-Determined Object Attributes). The lack of secure default controls results in a situation where any public attribute on an active LiveView session can be modified. This creates paths for unauthorized state manipulation and potential privilege escalation within affected Django applications.
The root cause of the vulnerability resides in the validation logic of the update_model event handler. The handler is designed to map client-side input field updates directly to server-side instance variables using Python's setattr built-in function. To prevent abuse, the developers introduced multiple validation checks, including an optional allowlist parameter named allowed_model_fields.
By default, the allowed_model_fields parameter was set to None. When this configuration was active, the framework implemented a fail-open behavior. The validation logic only verified that the requested field did not begin with an underscore, was not present in a static list of fourteen forbidden internal properties, and existed on the target object instance.
This behavior exposes any public variable bound to the LiveView instance to arbitrary mutation. If a developer defines a public helper variable or a state tracker on the view class, that variable is exposed to incoming WebSocket events. Because the type coercion utility automatically parses string parameters into matching primitive types, attackers can mutate booleans, integers, and other data types.
The vulnerable implementation depends on a permissive control structure that executes when a WebSocket frame containing an update_model payload is received. The following segment shows the logic path prior to the remediation in version 1.0.7.
# Vulnerable implementation in djust/mixins/model_binding.py
@event_handler
def update_model(self, field, value):
# Prevent modification of private or dunder attributes
if field.startswith('_'):
return
# Prevent modification of critical framework-level fields
if field in FORBIDDEN_MODEL_FIELDS:
return
# Verify that the attribute actually exists on the view
if not hasattr(self, field):
return
# Fail-open check: if no allowlist is configured, permit the update
if self.allowed_model_fields is not None and field not in self.allowed_model_fields:
return
# Dynamic modification of instance state
setattr(self, field, value)The patched version introduces an automated validation mechanism that extracts static template bindings during compilation. The template engine parses the abstract syntax tree (AST) to identify valid dj-model declarations and generates a safe auto-allowlist.
# Patched implementation in djust/mixins/model_binding.py
@event_handler
def update_model(self, field, value):
if field.startswith('_'):
return
if field in FORBIDDEN_MODEL_FIELDS:
return
if not hasattr(self, field):
return
# Retrieve developer-defined overrides
allowed = self.allowed_model_fields or set()
# Retrieve the AST-derived static bindings from the compiled template
auto_allowed = getattr(self, '_dj_model_fields', set())
# Fail-closed check: block updates if the field is not in either set
if field not in allowed and field not in auto_allowed:
return
# State mutation only occurs after validation passes
setattr(self, field, value)Exploitation requires an attacker to establish an active WebSocket connection to an application endpoint running a vulnerable LiveView instance. The attacker must target a view that contains sensitive state tracking within its public attributes. Because the handler executes without further session validation on individual attributes, any authenticated client can trigger the payload.
An attacker constructs a WebSocket event payload targeting the default event handler name. The payload contains parameters specifying the target field and the desired modification value. The following example represents the logical structure of an exploitation payload targeting a boolean privilege flag.
{
"type": "event",
"event": "update_model",
"params": {
"field": "is_admin",
"value": "true"
}
}Upon receiving this frame, the server-side component processes the request. The validation checks succeed because the field is public, not protected by a default allowlist, and exists on the target class. The framework automatically parses the string representation into a boolean value and updates the server-side state of the active connection.
The security impact of CVE-2026-61598 depends heavily on the design of the target Django application. Because LiveView instances manage local component state on the server, modifying public attributes allows attackers to bypass operational limits and application workflows. If a class exposes properties associated with user permissions or identifiers, attackers can elevate their privileges or access other accounts.
In transaction-oriented applications, this flaw can lead to financial tampering. For instance, if a checkout view stores a public variable representing a unit price or total quantity, an attacker can modify those values prior to final payment processing. The dynamic nature of the model binding means that changes propagate immediately through the server-side state machine.
The vulnerability has been assigned a CVSS score of 7.1, reflecting a high-severity rating. The attack complexity is low and no special privileges beyond basic authentication are required. The primary impact is to the integrity of the application state, as represented by the high integrity vector in the CVSS string.
The primary remediation path is upgrading the djust package to version 1.0.7 or later. The update switches the default validation mechanism to a secure, fail-closed posture. It leverages Rust AST compilation of templates to dynamically map valid client-side fields, ensuring that only declared inputs can trigger modifications.
If immediate patching is not feasible, developers must manually define the allowed_model_fields attribute on all existing LiveView components. This attribute must contain a set of strings representing the exact subset of variables intended for synchronization. Setting this value explicitly overrides the vulnerable fail-open default configuration.
class SecureLegacyView(LiveView):
# Manually declare permitted fields to neutralize the fail-open vulnerability
allowed_model_fields = {"search_query", "page_offset"}Additionally, developers must adhere to strict state isolation practices. Sensitive data, including database identifiers, privilege levels, and pricing values, should never be stored in public instance variables. Instead, use private variables or session storage to retain authorization contexts and critical business state.
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
djust djust-org | < 1.0.7 | 1.0.7 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-915 (Improperly Controlled Modification of Dynamically-Determined Object Attributes) |
| Attack Vector | Network |
| CVSS v4.0 | 7.1 |
| Exploit Status | None / No Public PoC |
| CISA KEV Status | Not Listed |
| Remediation | Upgrade to 1.0.7 or declare explicit allowed_model_fields |
The product allows an attacker to modify attributes of an object in a way that is not within the scope of the expected modification.
An untrusted search path vulnerability (CWE-426) in the OpenTelemetry.Resources.Host NuGet package on macOS allows a local attacker to execute arbitrary code with elevated privileges by hijacking standard system commands such as sh and ioreg.
An uncontrolled resource consumption vulnerability (CVE-2026-69213) in the http4s Ember HTTP/2 server and client implementations allows unauthenticated remote attackers to trigger an OutOfMemoryError (OOM) and cause a Denial of Service (DoS) by exploiting unbounded outbound queues.
CVE-2026-60137 is a critical SQL injection vulnerability in the Core component of WordPress. The flaw occurs within the WP_Query class during the processing of the author__not_in parameter, where user-supplied array inputs are constructed into a SQL string without strict integer type-casting. When chained with CVE-2026-63030, an unauthenticated remote attacker can exploit this SQL injection to read database values, extract administrator credential hashes, or modify administrative options to execute arbitrary PHP code on the server.
A validation flaw exists in the CookieJar client middleware of the http4s library. Prior to versions 0.23.35 and 1.0.0-M47, the middleware trusts server-supplied Domain attributes in HTTP Set-Cookie response headers without confirming that the domain matches the origin host. A malicious server can leverage this to register unauthorized cookies targeting different domains, creating potential session fixation or cookie poisoning vectors.
A medium-severity cross-origin cookie leakage vulnerability exists in the CookieJar client middleware of the http4s library. Due to unanchored substring searches used to determine whether a cookie applies to an outbound request, sensitive cookies (such as session IDs and credentials) can be inadvertently sent to unauthorized domains or paths.
An HTTP Request/Response Smuggling vulnerability (CVE-2026-69216) was identified in the Ember chunked transfer encoding decoder of the http4s Scala library. Due to parser leniency accepting sign prefixes, surrounding whitespace, and missing trailing CRLFs, attackers can bypass proxy security boundaries, poison shared caches, or hijack request queues.