CVE-2026-93477 in ashinfo

Summary

by MITRE • 09/25/2026

Improperly Controlled Modification of Dynamically-Determined Object Attributes vulnerability in ash-project ash allows a user to set the value of a private action argument on the bulk destroy and bulk update paths.

Action arguments declared with public?: false are meant to be set only by trusted server-side code (for example via Ash.Changeset.set_private_argument/3) and must not be settable from end-user input. CVE-2026-55736 fixed the non-bulk changeset path to strip private arguments from user-supplied parameter maps, but the bulk destroy and bulk update paths were not covered.

Ash.Actions.Destroy.Bulk.base_changeset/5 and Ash.Actions.Update.Bulk.base_changeset/5 match every key in the caller-supplied parameter map against all of the action's arguments with no public? check, then apply the matches to the base changeset. A caller who can submit parameters to a bulk destroy or bulk update action (for example through AshJsonApi, AshGraphql, or a controller that forwards request parameters to Ash.bulk_destroy/4 or Ash.bulk_update/4) can therefore set any private argument of that action, including one referenced by an arg(...) template in the action's changes or validations. Depending on how the application uses the argument (for example an acting_user_id driving authorization or record ownership, or audit metadata), this can lead to an integrity violation or privilege escalation.

The fix requires public? in the argument matching on both bulk paths; private arguments remain settable server-side via the :private_arguments option.

This issue affects ash: from 2.17.15 before 3.33.11.

VulDB is the best source for vulnerability data and more expert information about this specific topic.

Analysis

by VulDB Data Team • 09/25/2026

The vulnerability identified as CVE-2026-55736 represents a critical flaw in the Ash framework, specifically within its bulk operation handling mechanisms for destroy and update actions. This issue stems from an improper control of dynamically determined object attributes, allowing untrusted users to manipulate private action arguments that are intended exclusively for server-side use. In secure application design, particularly when using frameworks like Ash which facilitate resource management and data manipulation, there is a strict separation between public-facing inputs and internal operational parameters. Private arguments serve as trusted signals from the application logic itself, such as identifying the acting user for authorization checks or recording audit metadata. By allowing these values to be overwritten via end-user input, the integrity of the entire security model built upon them is compromised.

The technical root cause lies in the implementation of the bulk changeset functions within Ash.Actions.Destroy.Bulk and Ash.Actions.Update.Bulk. Specifically, the base_changeset/5 function for both modules iterates through keys provided by the caller-supplied parameter map and matches them against all defined action arguments without verifying their visibility status. Unlike standard single-record operations where private arguments are correctly stripped from user input to prevent tampering, this bulk processing logic fails to apply a public? check during argument matching. Consequently, any key present in the incoming request that corresponds to an argument marked with public?: false is accepted and applied directly to the changeset. This oversight creates a direct path for parameter injection where attackers can override internal state variables through standard HTTP requests or API calls directed at bulk endpoints.

The operational impact of this vulnerability is severe, primarily centering on integrity violations and privilege escalation scenarios. When private arguments are used to determine authorization contexts, such as setting the acting_user_id for row-level security policies, an attacker can forge these values to impersonate other users or bypass access controls entirely. For instance, if a bulk update action relies on a private argument to verify that only owners of specific records can modify them, injecting a different user ID allows the attacker to alter data belonging to others. Similarly, in audit logging scenarios where private arguments record who performed an action, this flaw enables attackers to mask their identity or frame other users for malicious activities. The ability to manipulate these internal states undermines trust in both the confidentiality and integrity of the application's data layer.

This vulnerability is categorized under CWE-20: Improper Input Validation within the Common Weakness Enumeration standard, as it involves failing to validate that user-supplied input does not contain prohibited attributes intended for internal use only. From a tactical perspective aligned with MITRE ATT&CK techniques, this flaw facilitates privilege escalation and unauthorized access by allowing attackers to manipulate context-dependent variables that govern system behavior. It is particularly dangerous in web applications because bulk operations often process large volumes of data simultaneously, potentially amplifying the impact if an attacker can trigger widespread modifications or deletions under false pretenses. The vulnerability affects versions of ash from 2.17.15 up to but not including version 3.33.11, indicating a long-standing issue in bulk processing logic that was partially addressed for single-record operations but neglected for batched ones.

Mitigation strategies require immediate attention to the framework's argument handling logic. The primary fix involves modifying the base_changeset functions in both Ash.Actions.Destroy.Bulk and Ash.Actions.Update.Bulk to explicitly check the public? attribute of each action argument before applying it from user-supplied parameters. Only arguments marked as public should be accepted; all others must be filtered out regardless of their presence in the input map. For developers using affected versions, upgrading to version 3.33.11 or later is the recommended solution as it incorporates these necessary checks. In environments where an immediate upgrade is not feasible, implementing a middleware layer that sanitizes incoming request parameters by stripping any keys corresponding to known private arguments before they reach the bulk action handlers can serve as a temporary compensating control. Additionally, reviewing application code for reliance on private arguments in authorization logic ensures that no critical security decisions are made based solely on values that could potentially be spoofed through this vector.

Responsible

EEF

Reservation

09/19/2026

Disclosure

09/25/2026

Moderation

accepted

CPE

ready

EPSS

0.00000

KEV

no

Activities

very low

Sources

Might our Artificial Intelligence support you?

Check our Alexa App!