| CVE |
Vendors |
Products |
Updated |
CVSS v3.1 |
| AshLua exposes Ash read actions to Lua scripts run through an eval action. A read call accepts an operation (list, min, max, first, sum, avg) that builds an ad-hoc Ash.Query.Aggregate over a named field and returns its raw value.
Ash field policies redact forbidden fields on returned records (replacing them with %Ash.ForbiddenField{}), but that redaction does not apply to aggregate values. A script could therefore read a field the calling actor's field policies forbid by requesting it as an aggregate instead of as a field. This includes fields that are public? true but restricted per-actor by a field policy, such as sensitive PII. The prior hardening only enforced the exposed-field allow-list (field visibility), which is a separate axis from per-actor field-policy authorization.
The fix authorizes the aggregated field against the resource's field policies, so aggregating over a field the actor may not see is refused or scoped to the rows where it is visible.
This issue affects ash_lua: from 0.1.0 before 0.2.2. |
| AshAi exposes Ash read actions to language-model tool calls. The read tool accepts an aggregate result type (min, max, sum, avg) that builds an ad-hoc Ash.Query.Aggregate over a named field and returns its raw value.
Ash field policies redact forbidden fields on returned records (replacing them with %Ash.ForbiddenField{}), but that redaction does not apply to aggregate values. A tool caller could therefore read a field the calling actor's field policies forbid by requesting it as an aggregate; min/max in particular return an actual field value. This includes fields that are public? true but restricted per-actor by a field policy, such as sensitive PII. The tool's existing check only required the field to be public, which is a separate axis from per-actor field-policy authorization.
The fix authorizes the aggregated field against the resource's field policies, so aggregating over a field the actor may not see is refused or scoped to the rows where it is visible.
This issue affects ash_ai: from 0.1.0 before 1.0.3. |
| Improper Validation of Specified Quantity in Input vulnerability in ash-project ash allows an attacker to store a value of arbitrary size in an attribute whose length constraint should bound it.
Ash measures string length with Elixir's String.length/1, which counts Unicode graphemes, in the max_length and min_length constraints of Ash.Type.String (apply_constraints/2 in lib/ash/type/string.ex), in Ash.Resource.Validation.StringLength, and in the string_length expression function. A grapheme carries an unbounded number of combining marks, so a base character followed by a million combining acute accents is one grapheme and megabytes of data, and satisfies max_length: 2. Where the data layer imposes no independent limit (ETS, Mnesia, or a Postgres text column) the whole value is persisted, so an attacker can write an entire request body into an attribute declared with a small maximum and grow storage without bound.
The counting unit also disagrees with the storage layer, which counts codepoints rather than graphemes, so a value accepted by the constraint can still be rejected or truncated by the column. A Postgres varchar(n) column bounds the value itself and is not exposed.
This issue affects ash: from 0.10.0 before 3.33.0. |
| Improper Authentication vulnerability in ash-project ash_authentication_oauth2_server allows an unauthenticated attacker to register OAuth clients even when Dynamic Client Registration is gated by an initial access token.
resolve_secret/3 in AshAuthentication.Oauth2Server (reached through __resolve_secret__!) treated any return other than {:ok, _} or :error from a configured {module, function, args} or 2-arity-function secret provider as a valid secret, wrapping nil, false, or "" as {:ok, value}. When the initial_access_token resolves to such an empty value, POST /oauth/register compares the presented bearer token against it and the comparison passes with no token supplied, so registration is open although it was configured closed. The same fail-open affected other resolved secrets such as signing_secret.
This issue affects ash_authentication_oauth2_server: from 0.1.0 before 0.3.1. |
| Server-Side Request Forgery (SSRF) vulnerability in ash-project ash_authentication_oauth2_server allows an attacker who controls a client metadata URL and its DNS to make the server connect to internal or loopback addresses.
public_ip?/1 in AshAuthentication.Oauth2Server.CIMD.ReqFetcher enforces the outbound policy for CIMD metadata fetches. It classified several address forms as publicly routable that are not: IPv4-compatible ::/96 (for example ::127.0.0.1), SIIT IPv4-translated ::ffff:0:0:0/96, and deprecated site-local fec0::/10. A returned AAAA record in one of these ranges passed the policy, so a fetch pinned to that address reached space the policy was meant to block.
This issue affects ash_authentication_oauth2_server: from 0.3.0 before 0.3.1. |
| Improper Encoding or Escaping of Output vulnerability in ash-project ash_authentication_oauth2_server allows an unauthenticated attacker to inject arbitrary authentication parameters into the WWW-Authenticate challenge header.
BearerPlug and RequireScopePlug built the Bearer resource_metadata="..." challenge by interpolating a resource_metadata URL derived from the request tenant directly into the quoted value. In a multi-tenant application that sets the Ash tenant from request-controlled data (a subdomain, the Host, a path segment, or a header), a tenant containing a " closes the quoted value and appends attacker-chosen auth-params, including a second resource_metadata URL pointing at an attacker-controlled authorization server that spec-following clients follow. Carriage returns and line feeds are rejected by Plug, so this is parameter injection within one header, not response splitting.
This issue affects ash_authentication_oauth2_server: from 0.1.3 before 0.3.1. |
| Use of Cache Containing Sensitive Information vulnerability in ash-project ash_authentication_oauth2_server allows a shared HTTP cache to serve one tenant's OAuth discovery metadata to another tenant's clients.
The RFC 8414 and RFC 9728 metadata endpoints in AshAuthentication.Phoenix.Oauth2Server.ProtocolRouter return tenant-specific values (issuer, authorization_endpoint, token_endpoint, jwks_uri) when a tenant is set, but sent them with Cache-Control: public, max-age=3600 and no Vary. When the tenant is derived from something other than the URL (a header or the Host) and a shared cache sits in front, the cache key is the URL alone, so a stored response for one tenant is served to another for up to an hour. Affected clients may then send authorization codes and secrets to the wrong tenant's token endpoint and validate tokens against the wrong keys.
This issue affects ash_authentication_oauth2_server: from 0.1.3 before 0.3.1. |
| Improper Protection of Alternate Path vulnerability in ash-project ash_authentication_oauth2_server exposes the state-changing OAuth endpoints under an unintended URL prefix, bypassing controls scoped to the canonical prefix.
oauth2_server_protocol_routes/1 in AshAuthentication.Phoenix.Oauth2Server.Router forwards the same ProtocolRouter at both the /oauth prefix and the /.well-known prefix. Phoenix forward strips the matched prefix before dispatch, so the full route table answers under both mounts, and POST /register, POST /token, and POST /revoke are reachable as /.well-known/register, /.well-known/token, and /.well-known/revoke. Edge controls such as WAF rules, rate limits, or authentication exemptions written against the /oauth paths, or that allow-list /.well-known as unauthenticated, do not apply to the alias.
This issue affects ash_authentication_oauth2_server: from 0.1.0 before 0.3.1. |
| Allocation of Resources Without Limits or Throttling vulnerability in ash-project ash_authentication_oauth2_server allows an unauthenticated attacker to exhaust database storage and memory.
The /authorize endpoint is unauthenticated by design. With Client ID Metadata Documents enabled, resolve_client/3 in AshAuthentication.Oauth2Server.CIMD fetches the document for each new URL-shaped client_id and upserts a client row, with no cap on the number of rows, no expiry or garbage collection, and no length bound on the fetched fields; the document was also placed in CIMD.Cache before validation, so even rejected documents held cache memory until their TTL. An attacker serving valid documents at many distinct URLs creates one permanent client row per URL, each able to carry multi-megabyte strings, growing storage and memory without bound.
This issue affects ash_authentication_oauth2_server: from 0.3.0 before 0.3.1. |
| Improper Neutralization of Escape, Meta, or Control Sequences vulnerability in ash-project usage_rules allows a malicious package publisher to inject terminal control sequences into the output of mix usage_rules.search_docs.
mix usage_rules.search_docs searches Hex documentation through search.hexdocs.pm, which indexes the documentation of every published package, and prints the matching results (title, package, type, doc reference, and highlighted snippets) to the terminal. The formatter in Mix.Tasks.UsageRules.SearchDocs interpolated those publisher-controlled fields verbatim, neutralizing no terminal control characters; the only transform it applied adds escape sequences rather than removing them. A malicious package can embed ANSI terminal escape sequences (cursor movement, line erase, carriage returns, OSC 52 clipboard writes) in its indexed documentation, so when a developer runs a search that surfaces those docs the sequences reach the terminal unchanged — forging the displayed hexdocs URL or a suggested command, hiding text, or writing to the clipboard. No authentication or privileged position is required; only publishing a package.
This issue affects usage_rules: from 0.1.18 before 1.2.8. |
| Improper Protection of Alternate Path vulnerability in ash-project ash_lua allows a user-supplied Lua script to read attributes that are not on the exposed-field allow-list.
AshLua exposes Ash resources to Lua scripts, gated by a manifest declaring which fields are exposed. The read action's operation aggregate path in AshLua.Runtime took the field name straight from the Lua call and resolved it with only String.to_existing_atom and Ash.Query.Aggregate.new!, neither of which consults the exposed-field allow-list the normal fields path enforces. A script can therefore read the value of any attribute of any record the actor may read, including private sensitive?: true columns, via resource.read({ operation = {"list", "hashed_password"} }); min and max give a value oracle. Anyone able to submit or influence a Lua script can reach this.
This issue affects ash_lua: from 0.1.0 before 0.2.1. |
| Improper Neutralization of Escape, Meta, or Control Sequences vulnerability in ash-project igniter allows a malicious package publisher to forge the mix igniter.install confirmation prompt.
mix igniter.install prints a confirmation panel (an anti-typosquatting safeguard) listing a package's hex metadata before adding it. The panel builder in Igniter.Project.Deps wrote publisher-controlled fields (meta.description, owner usernames, requirement names, version) to the terminal with only newlines stripped. A malicious or typosquatted package can embed ANSI terminal escape sequences (cursor movement, line erase, carriage returns) in its metadata to overwrite the panel, forging trusted author names and download counts while concealing the real ones, so a developer relying on the panel to vet the package is deceived into approving a malicious dependency.
This issue affects igniter: from 0.8.1 before 0.8.4. |
| Improper Handling of Alternate Encoding vulnerability in ash-project ash_double_entry allows an attacker to submit several distinct string spellings of the same identifier.
AshDoubleEntry.ULID renders a 128-bit ULID as 26 Crockford base-32 characters, but the first character encodes only 3 bits, so canonical values are 0 to 7. decode/1 in lib/ulid.ex masks the first character to its low 3 bits and valid?/1 accepts all 32 characters in that position, so 0..., 8..., G... and R... decode to the identical 16-byte value and resolve to the same row. When the type is exposed as a public ID over an HTTP or API boundary, an attacker-supplied ID can be spelled differently from the record it actually reads or writes, desynchronizing or bypassing string-level checks such as idempotency and deduplication keys, deny-lists, audit correlation, or signatures computed over the submitted ID.
This issue affects ash_double_entry: from 0.1.0 before 1.0.19. |
| Improper Validation of Specified Quantity in Input vulnerability in ash-project ash allows an attacker to submit a non-finite decimal value that bypasses numeric bounds constraints or fails later operations on the value.
Ash.Type.Decimal cast input through Ecto's decimal cast in cast_input/2 and cast_stored/2 (lib/ash/type/decimal.ex) without checking that the resulting value is finite. Elixir's Decimal represents Infinity and NaN as valid structs, so a value such as "Infinity" or "NaN" passed casting and was persisted. Because NaN compares as false against every bound, min and max constraints do not reject it, and the stored special value later raises when used in Decimal arithmetic or is refused by the data layer, failing subsequent requests. The fix rejects any non-finite Decimal during casting.
This issue affects ash: from 1.28.0 before 3.32.2. |
| Generation of Error Message Containing Sensitive Information vulnerability in ash-project ash_typescript allows an unauthenticated attacker to receive unredacted internal error data by provoking an error shape the configured error handler does not match.
apply_error_handler/3 in lib/ash_typescript/rpc/errors.ex is the only hook an application has for redacting or suppressing errors before they reach the client, with a nil return dropping the error entirely. Its rescue clause logs a warning and then returns the original, pre-handler error map. Error handlers are conventionally written as pattern-matching functions over expected error shapes, so an unmatched shape raises FunctionClauseError and the raw transformed error, including any secrets carried in vars, is emitted instead. An intent to suppress an error becomes an intent to publish it. The rescue catches exceptions only, so a handler that throws or exits still propagates.
This issue affects ash_typescript: from 0.8.0 before 0.18.0. |
| Authorization Bypass Through User-Controlled Key vulnerability in ash-project ash_phoenix lets an attacker who controls filter form parameters filter across relationships the resource author marked non-public, turning the returned rows into a boolean oracle over private related data.
AshPhoenix.FilterForm resolved every relationship hop in the user-supplied path with Ash.Resource.Info.related/2, which traverses private relationships, and only checked the terminal field for publicity. parse_path_and_field/2 also rewrote a field naming a relationship into an extra path segment, so field=some_private_rel was accepted too. Both path and field come straight from form params, and the resulting ref went to Ash.Query.do_filter/2 without the public-only enforcement of Ash.Filter.parse_input/2. The fix resolves each hop with Ash.Resource.Info.public_relationship/2, rejecting the first non-public hop, and requires the terminal field to be public.
This issue affects ash_phoenix: from 0.6.0-rc.1 before 2.3.25. |
| Unchecked Return Value vulnerability in ash-project ash_postgres allows a user who can drive a tenant rename to a name that collides with an existing tenant's schema to have their tenant record repointed at that other tenant's live schema, gaining access to its data.
AshPostgres.MultiTenancy.rename_tenant/3 issues the ALTER SCHEMA ... RENAME TO ... with the non-raising Ecto.Adapters.SQL.query/2, discards its {:ok, _} | {:error, _} result, and unconditionally returns :ok. PostgreSQL rejects the rename when the target schema already exists (and on insufficient privilege or lock timeout), but that failure never reaches the caller. The calling manage_tenant update action therefore sees success and commits the tenant row with the new name, which is the schema of a different existing tenant, so subsequent reads and writes for that tenant run against the other tenant's data.
This issue affects ash_postgres: from 0.25.0 before 2.13.0. |
| Allocation of Resources Without Limits or Throttling vulnerability in ash-project ash_typescript allows an unauthenticated attacker to exhaust the BEAM atom table and abort the node via client-supplied RPC field names.
AshTypescript.FieldFormatter.convert_to_field_atom/2 in lib/ash_typescript/field_formatter.ex converts a client-supplied field name to an atom with String.to_atom/1 when no matching atom already exists. It delegates first to parse_input_field/2, which resolves the name with String.to_existing_atom/1 and falls back to returning the plain string; convert_to_field_atom/2 then mints an atom from that string rather than treating the name as unknown.
RPC field selection reaches it for every requested field name through AshTypescript.Rpc.FieldProcessing.FieldSelector, which resolves each name before checking that the field exists, with no allowlist, length bound, or rate limit. Atoms are never garbage collected, so each distinct name mints a permanent one and the VM aborts once the atom table limit is reached. A field name over 255 characters additionally raises an uncaught SystemLimitError.
This issue affects ash_typescript: from 0.1.0 before 0.18.0. |
| Exposure of Data Element to Wrong Session vulnerability in ash-project ash_graphql can deliver one subscription's resolved records to a different subscriber's topic.
AshGraphql.Subscription.Batcher.do_send/5 reads the resolved batch from the process dictionary via Process.get(:batch_resolved) and then unconditionally deletes it. That is sound only inside a task the library owns. On the :backpressure_sync and :noproc fallbacks do_send/5 runs inline in the publishing caller's process, so if a resolver inside an outer do_send/5 triggers another synchronous Ash notification, the inner call finds the outer run's value still under :batch_resolved, adopts it as its own result, and publishes it to the inner topic, a different subscription document with a different actor and tenant. It then deletes the key, so the outer run publishes nothing. The key is not namespaced by run, so records cannot be told apart. The fix saves, clears, and restores :batch_resolved around each run.
This issue affects ash_graphql: from 1.4.0 before 1.11.0. |
| Incorrect Authorization vulnerability in ash-project ash_typescript allows an unauthorized RPC caller to read attribute values that Ash field policies denied.
When a field policy denies an attribute, Ash substitutes %Ash.ForbiddenField{}, which retains the real value in original_value because embedded resources must remain writable, and hides it from Inspect rather than removing it. AshTypescript.Rpc.ResultProcessor strips these markers to nil on its template-driven paths, but normalize_primitive/1 in lib/ash_typescript/rpc/result_processor.ex had no such clause, so a marker fell through to the generic struct branch which calls Map.from_struct/1 and serializes every key, original_value included. The denied value is returned to the caller inside the marker that represents its own denial.
The simplest trigger is an action returning an embedded resource as a map, which routes through normalize_resource_struct/2 with an empty template. normalize_value_for_json/1 is a public, unguarded entry point to the same path.
This issue affects ash_typescript: from 0.11.0 before 0.18.0. |