VYPR
High severityOSV Advisory· Published Sep 7, 2025· Updated Apr 15, 2026

CVE-2025-48042

CVE-2025-48042

Description

Incorrect Authorization vulnerability in ash-project ash allows Exploiting Incorrectly Configured Access Control Security Levels. This vulnerability is associated with program files lib/ash/actions/create/bulk.ex, lib/ash/actions/destroy/bulk.ex, lib/ash/actions/update/bulk.ex and program routines 'Elixir.Ash.Actions.Create.Bulk':run/5, 'Elixir.Ash.Actions.Destroy.Bulk':run/6, 'Elixir.Ash.Actions.Update.Bulk:run'/6.

This issue affects ash: from pkg:hex/ash before pkg:hex/ash@3.5.39, before 3.5.39, before 5d1b6a5d00771fd468a509778637527b5218be9a.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
ashHex
< 3.5.393.5.39

Affected products

1

Patches

2
5d1b6a5d0077

fix: authorize before before_transaction hooks in bulk actions

https://github.com/ash-project/ashZach DanielSep 6, 2025via ghsa
4 files changed · +106 10
  • lib/ash/actions/create/bulk.ex+3 3 modified
    @@ -501,6 +501,7 @@ defmodule Ash.Actions.Create.Bulk do
               changeset.action.require_attributes
             )
           end)
    +      |> authorize(opts)
           |> Ash.Actions.Helpers.split_and_run_simple(
             action,
             opts,
    @@ -645,9 +646,8 @@ defmodule Ash.Actions.Create.Bulk do
             end)
     
         batch =
    -      batch
    -      |> authorize(opts)
    -      |> Ash.Actions.Update.Bulk.run_bulk_before_batches(
    +      Ash.Actions.Update.Bulk.run_bulk_before_batches(
    +        batch,
             changes,
             all_changes,
             opts,
    
  • lib/ash/actions/destroy/bulk.ex+4 4 modified
    @@ -1433,6 +1433,8 @@ defmodule Ash.Actions.Destroy.Bulk do
             :bulk_destroy
           )
     
    +    batch = authorize(batch, opts)
    +
         batch =
           if re_sort? do
             Enum.sort_by(batch, & &1.context.bulk_destroy.index)
    @@ -1611,10 +1613,8 @@ defmodule Ash.Actions.Destroy.Bulk do
             end)
     
         batch =
    -      batch
    -      |> authorize(opts)
    -      |> Enum.to_list()
    -      |> Ash.Actions.Update.Bulk.run_bulk_before_batches(
    +      Ash.Actions.Update.Bulk.run_bulk_before_batches(
    +        batch,
             changes,
             all_changes,
             opts,
    
  • lib/ash/actions/update/bulk.ex+4 3 modified
    @@ -1751,6 +1751,8 @@ defmodule Ash.Actions.Update.Bulk do
             context_key
           )
     
    +    batch = authorize(batch, opts)
    +
         batch =
           if re_sort? do
             Enum.sort_by(batch, & &1.context[context_key].index)
    @@ -1920,9 +1922,8 @@ defmodule Ash.Actions.Update.Bulk do
             end)
     
         batch =
    -      batch
    -      |> authorize(opts)
    -      |> run_bulk_before_batches(
    +      run_bulk_before_batches(
    +        batch,
             changes,
             all_changes,
             opts,
    
  • test/policy/simple_test.exs+95 0 modified
    @@ -654,4 +654,99 @@ defmodule Ash.Test.Policy.SimpleTest do
     
         assert user2_got_thing.id == user2_thing.id
       end
    +
    +  defmodule ResourceWithBeforeTransactionHook do
    +    use Ash.Resource,
    +      domain: Ash.Test.Domain,
    +      authorizers: [Ash.Policy.Authorizer]
    +
    +    attributes do
    +      uuid_primary_key :id
    +      attribute :name, :string, public?: true
    +    end
    +
    +    actions do
    +      defaults [:read]
    +
    +      create :create do
    +        primary? true
    +        accept [:name]
    +      end
    +
    +      update :test_action_with_after_transaction do
    +        accept [:name]
    +
    +        change before_transaction(fn changeset, _context ->
    +                 raise "running before transaction"
    +               end)
    +
    +        change after_transaction(fn _changeset, res, _context ->
    +                 res
    +               end)
    +
    +        require_atomic? false
    +      end
    +
    +      update :test_action_without_after_transaction do
    +        accept [:name]
    +
    +        change before_transaction(fn changeset, _context ->
    +                 raise "running before transaction"
    +               end)
    +
    +        require_atomic? false
    +      end
    +    end
    +
    +    policies do
    +      policy action_type(:read) do
    +        authorize_if always()
    +      end
    +
    +      policy action_type(:create) do
    +        authorize_if always()
    +      end
    +    end
    +  end
    +
    +  test "before_transaction hook should not run when action is not authorized via bulk_update" do
    +    record = Ash.create!(ResourceWithBeforeTransactionHook, %{name: "test"}, authorize?: false)
    +
    +    query =
    +      ResourceWithBeforeTransactionHook
    +      |> Ash.DataLayer.Simple.set_data([record])
    +      |> Ash.Query.limit(1)
    +
    +    assert_raise Ash.Error.Forbidden, fn ->
    +      Ash.bulk_update!(query, :test_action_with_after_transaction, %{},
    +        return_errors?: true,
    +        notify?: true,
    +        strategy: [:atomic, :stream, :atomic_batches],
    +        allow_stream_with: :full_read,
    +        authorize_changeset_with: :filter,
    +        return_records?: true,
    +        authorize?: true,
    +        read_action: :read,
    +        domain: Ash.Test.Domain,
    +        select: [],
    +        load: []
    +      )
    +    end
    +
    +    assert_raise Ash.Error.Forbidden, fn ->
    +      Ash.bulk_update!(query, :test_action_without_after_transaction, %{},
    +        return_errors?: true,
    +        notify?: true,
    +        strategy: [:atomic, :stream, :atomic_batches],
    +        allow_stream_with: :full_read,
    +        authorize_changeset_with: :filter,
    +        return_records?: true,
    +        authorize?: true,
    +        read_action: :read,
    +        domain: Ash.Test.Domain,
    +        select: [],
    +        load: []
    +      )
    +    end
    +  end
     end
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.