logo

Lack of data validation - Responses - Elixir


Need

Maintain data integrity by server-side validation of input data


Context

  1. Usage of Elixir (1.12 and above) for building scalable and fault-tolerant applications
  2. Usage of Plug for request handling

Description

Insecure Code Example

defmodule UserController do
  use MyApp.Web, :controller

  def show(conn, params) do
    user = Repo.get(User, params["id"])
    render(conn, "show.json", user: user)
  end

  def update(conn, params) do
    user = Repo.get(User, params["id"])
    user_changes = Map.from_struct(params["user"])
    changeset = User.changeset(user, user_changes)
    case Repo.update(changeset) do
      {:ok, user} ->
        render(conn, "show.json", user: user)
      {:error, changeset} ->
        conn
        |> put_status(:unprocessable_entity)
        |> render(MyApp.ChangesetView, "error.json", changeset: changeset)
    end
  end
end

This code fetches a user record and sends it in the response, then takes user data from a subsequent request and updates the user record without any validation. If the received data is invalid, it could lead to data integrity issues.

Steps

  1. Validate the incoming data before updating the record.
  2. If the data is not valid, return an error response.

Secure Code Example

defmodule UserController do
  use MyApp.Web, :controller

  def show(conn, params) do
    user = Repo.get(User, params["id"])
    render(conn, "show.json", user: user)
  end

  def update(conn, params) do
    user = Repo.get(User, params["id"])
    user_changes = Map.from_struct(params["user"])
    if valid_user_data?(user_changes) do
      changeset = User.changeset(user, user_changes)
      case Repo.update(changeset) do
        {:ok, user} ->
          render(conn, "show.json", user: user)
        {:error, changeset} ->
          conn
          |> put_status(:unprocessable_entity)
          |> render(MyApp.ChangesetView, "error.json", changeset: changeset)
      end
    else
      send_resp(conn, 400, "Invalid user data")
    end
  end

  defp valid_user_data?(data) do
    # Implement validation logic here
  end
end

In the secure code example, the incoming user data is validated before it is used to update the user record. If the data is not valid, an error response is returned. This prevents an attacker from submitting invalid data.


References

  • 191 - Lack of data validation - Responses

  • Last updated

    2023/09/18