HIGH mass assignmentchijwt tokens

Mass Assignment in Chi with Jwt Tokens

Mass Assignment in Chi with Jwt Tokens — how this specific combination creates or exposes the vulnerability

Mass assignment is a property-level authorization issue where an attacker can set fields that should be immutable or controlled by the server. In Chi, this often occurs when route parameters or body payloads are bound directly to a model or record without explicit filtering. When Jwt Tokens are involved, the risk intensifies because developers may trust claims embedded in the token to authorize updates, while also using those same claims to drive mass assignment logic.

For example, a Chi route that decodes a Jwt Token to extract a user identifier and then binds incoming JSON directly to an Ecto changeset can inadvertently allow an attacker to modify sensitive fields such as role, permissions, or admin status. If the changeset uses Ecto.Changeset.cast(params, ~w()a field)a list) with a broad field list derived from token claims or session data, an attacker who obtains or guesses a token can escalate privileges by assigning fields like is_admin or role.

Even when Jwt Tokens are validated and the subject or scopes are inspected, mass assignment may still occur if the application merges token-derived metadata with request parameters before passing them to the data layer. Chi does not automatically prevent this; it relies on the developer to define which fields are assignable per context. Without strict allowlists, an attacker can exploit overly permissive bindings to modify resources they should not access, leading to vertical or horizontal privilege escalation.

Real-world attack patterns include an authenticated user sending a PATCH request with an added is_superuser field, or including crafted claims in a Jwt Token that reference higher-privilege roles. When combined with weak parameter filtering, such requests can change ownership or permissions in the database. This maps to the OWASP API Top 10 API1:2023 – Broken Object Level Authorization and can violate compliance frameworks such as SOC 2 and GDPR when sensitive attributes are modified unintentionally.

Jwt Tokens-Specific Remediation in Chi — concrete code fixes

Remediation focuses on strict field allowlisting and keeping Jwt Token usage for authentication and authorization metadata separate from mass assignment inputs. Always bind only the fields you intend to update, and do not derive the assignable field list from token claims.

Example: Unsafe binding with Jwt Token claims

defmodule MyAppWeb.UserController do
  use MyAppWeb, :controller

  # UNSAFE: directly casting all keys from the body
  def update(conn, %{"id" => id, "user" => user_params}) do
    # Assume token claims include role — do NOT use them to build the field list
    changeset = User.changeset(user, user_params) # vulnerable to mass assignment
    # ... handle changeset
  end
end

Example: Safe, explicit allowlist with Jwt Token metadata

defmodule MyAppWeb.UserController do
  use MyAppWeb, :controller
  import MyApp.Accounts, only: [update_user: 2]

  # SAFE: explicit fields, ignoring any attacker-supplied fields
  def update(conn, %{"id" => id, "user" => user_params}) do
    # Decode Jwt Token early to get subject and scopes, but do not use for casting
    with {:ok, claims} <- MyApp.Auth.verify_jwt(conn), # returns %{sub: user_id, scopes: [...]}
         true <- claims["sub"] == id, # ensure user can only update themselves
         changeset <- User.update_changeset(id, user_params) do # explicit function
      # proceed with authorized update
    end
  end
end

Define your changeset with a strict list of permitted fields per context. Never use dynamic field lists derived from tokens or session data.

Safe changeset definition

defmodule MyApp.Accounts.User do
  use Ecto.Schema
  import Ecto.Changeset

  schema "users" do
    field :email, :string
    field :username, :string
    field :role, :string
    # do NOT include :is_admin or :permissions in the default update form
    timestamps()
  end

  # Public changeset for registration — limited fields
  def registration_changeset(user, params) do
    user
    |> cast(params, [:email, :username])
    |> validate_required([:email, :username])
  end

  # Admin-specific changeset — explicit allowlist
  def admin_update_changeset(user, params) do
    user
    |> cast(params, [:email, :username, :role])
    |> validate_required([:email, :username])
  end

  # Contextual update changeset used by controllers — explicit per action
  def update_changeset(user_id, params) do
    # Fetch user separately; do not rely on params for IDs
    user = MyApp.Repo.get!(User, user_id)
    user
    |> cast(params, [:email, :username])
    |> validate_required([:email, :username])
  end
end

In your Chi pipeline, validate the Jwt Token and extract claims, but do not plug those claims into the casting step. Use them only for authorization decisions after the changeset is built. If you need role or scope checks, perform them explicitly before invoking the update function.

Chi pipeline example with token validation and safe binding

defmodule MyAppWeb.Router do
  use MyAppWeb, :router
  import MyAppWeb.AuthPlug, only: [require_jwt: 2]

  pipeline :api do
    plug :accepts, ["json"]
    plug require_jwt
  end

  scope "/api", MyAppWeb do
    pipe_through :api

    patch "/users/:id", UserController, :update
  end
end

defmodule MyAppWeb.AuthPlug do
  import Plug.Conn

  def require_jwt(conn, _opts) do
    case extract_and_validate(conn) do
      {:ok, claims} ->
        # Attach claims for later use, not for mass assignment
        assign(conn, :jwt_claims, claims)

      {:error, _} ->
        send_resp(conn, 401, "Unauthorized")
        halt(conn)
    end
  end

  defp extract_and_validate(conn) do
    # Extract token from bearer header, validate, and return claims
    # This is a placeholder for real Jwt handling logic
    {:ok, %{sub: "user-123", scopes: ["update:own_profile"]}}
  end
end

By keeping Jwt Token validation separate and using explicit allowlists in your changesets, you mitigate mass assignment risks even when tokens are present. This approach aligns with OWASP API Top 10 guidance and helps satisfy compliance requirements without over-relying on token metadata for data binding.

Related CWEs: propertyAuthorization

CWE IDNameSeverity
CWE-915Mass Assignment HIGH

Frequently Asked Questions

Can Jwt Token claims be used to filter which fields can be updated?
Claims should not be used to dynamically build field allowlists. Use them only for authorization checks after applying a strict, predefined allowlist in your changeset.
Does middleBrick detect mass assignment risks involving Jwt Tokens?
middleBrick scans unauthenticated attack surfaces and can identify parameter pollution and over-permissive binding patterns that may indicate mass assignment issues, including contexts involving Jwt Tokens.