CVE-2026-61598: Client mass-assignment of arbitrary view attributes via the default dj-model update_model handler

Published Sep 16, 2026
·
Updated

Impact djust.mixins.modelbinding.ModelBindingMixin provides a default updatemodel event handler and is part of the LiveView base MRO, so every LiveView exposes it. It setattrs a view attribute whose name is client-supplied (field), gated only by: reject -prefixed names; reject a 14-entry denylist of framework internals (FORBIDDENMODELFIELDS); optional allowedmodelfields which defaults to None = allow all; and hasattr existence.

Result: a client can set any public, existing view attribute — not just the fields actually bound with dj-model= in the rendered template. The denylist covers framework plumbing but nothing about developer business/authz state, and the allowlist is opt-in (off by default). A developer who binds one dj-model="search" input and also keeps self.accountid / self.isadmin / self.totalprice as view state does not realize a client can set ALL of them via {type:event, event:"updatemodel", params:{field, value}} over the WebSocket. Type coercion matches the target attribute's type (so "true" -> bool True), aiding the attacker.

Severity High for apps that hold authorization/ownership/business state in public view attributes (the normal djust pattern) -> state tampering / IDOR / authz-flag manipulation; Low otherwise. Default-on across every LiveView. For a public (no-login) view an anonymous client can mass-assign; for an authenticated view a logged-in user can tamper their own session's view state (the IDOR/authz vector when downstream handlers act on it without re-authorizing).

Reproduced: a view with accountid/isadmin/totalprice (none bound with dj-model) had all three set via updatemodel calls.

Patches Restrict the default handler to fields actually exposed via dj-model=: have the template renderer record the bound-field set per render and reject any field outside it (preferred, secure + zero-config); or make allowedmodelfields fail-closed (required). Keep FORBIDDENMODELFIELDS only as defense-in-depth. Add a regression that a non-dj-model public attribute (e.g. isadmin) is rejected while a bound field still updates.

Workarounds Set allowedmodelfields explicitly on every view using dj-model (or subclassing LiveView) to the minimal list of bindable fields; do not keep authorization/ownership state in public view attributes that share the view with dj-model bindings.

References Reproducer + finding writeup retained privately by the maintainer.

Other sources

djust provides Phoenix LiveView-style reactive server-side rendering for Django with Rust-powered performance. Prior to version 1.0.7, djust.mixins.modelbinding.ModelBindingMixin provides a default updatemodel event handler and is part of the LiveView base MRO, so every LiveView exposes it. It setattrs a view attribute whose name is client-supplied (field), gated only by: reject -prefixed names; reject a 14-entry denylist of framework internals (FORBIDDENMODELFIELDS); optional allowedmodelfields which defaults to None = allow all; and hasattr existence. As a result, a client can set any public, existing view attribute — not just the fields actually bound with dj-model= in the rendered template. The denylist covers framework plumbing but nothing about developer business/authz state, and the allowlist is opt-in (off by default). A developer who binds one dj-model="search" input and also keeps self.accountid / self.isadmin / self.totalprice as view state does not realize a client can set ALL of them via {type:event, event:"updatemodel", params:{field, value}} over the WebSocket. Type coercion matches the target attribute's type (so "true" -> bool True), aiding the attacker. This issue is fixed in djust 1.0.7. As a workaround, set allowedmodelfields explicitly on every view using dj-model (or subclassing LiveView) to the minimal list of bindable fields; do not keep authorization/ownership state in public view attributes that share the view with dj-model bindings.

MITRE

Affected Software

2 affected componentsFixes available
djust djust.mixins.model_binding.ModelBindingMixin<1.0.7
pip/djust<1.0.7
1.0.7

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/djust to a version that resolves this vulnerability.

    Fixed in 1.0.7
  2. Upgrade

    Upgrade djust.mixins.model_binding.ModelBindingMixin to a version that resolves this vulnerability.

    Fixed in 1.0.7
  3. Configuration

    Set `allowed_model_fields` explicitly on every LiveView using `dj-model=` to the minimal list of bindable fields. Do not rely on the default (`None` = allow all).

    djust LiveView dj-model allowed_model_fields = explicit minimal list per view
  4. Configuration

    Remove/avoid storing authorization/ownership/business state (e.g., `account_id`, `is_admin`, `total_price`) in public view attributes that coexist in the same view as `dj-model=` bindings, since the default `update_model` handler allows setting any public existing attribute.

    djust LiveView dj-model public view attributes usage = do not store authorization/ownership/business state in public view attributes that share the view with dj-model bindings

Event History

Sep 16, 2026
Advisory Published
via GitHub·01:55 PM
Data Sourced
via GitHub·01:55 PM
DescriptionWeaknessAffected Software
CVE Published
via MITRE·01:59 PM
Data Sourced
via MITRE·01:59 PM
DescriptionWeakness

Frequently Asked Questions

1

Which applications are exposed by default?

LiveViews using the affected ModelBindingMixin are exposed because its update_model handler is part of the LiveView base MRO. The optional allowed_model_fields restriction defaults to None, which permits all public existing view attributes unless they are on the framework denylist.

2

What does an attacker need to exploit this?

An attacker needs to send an update_model event over the LiveView WebSocket with a chosen field name and value. The target field must be a public, existing attribute on the view and must not start with an underscore or appear in FORBIDDEN_MODEL_FIELDS.

3

What kinds of application state should be reviewed first?

Review public view attributes that influence identity, authorization, pricing, account selection, or other business decisions. Attributes such as account_id, is_admin, and total_price are not protected merely because they were not bound with dj-model in the rendered template.

4

What can be done before upgrading?

Define allowed_model_fields explicitly so that only intended model-bound fields can be updated. Do not rely on the built-in denylist to protect application-specific state.

5

Which version addresses the affected behavior?

The issue affects versions prior to 1.0.7. Upgrade to version 1.0.7 or later.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203