AshPhoenixTranslations.LocaleValidator (ash_phoenix_translations v1.0.0)

View Source

Secure locale and field validation to prevent atom exhaustion attacks.

This module provides safe validation for user-provided locale codes and field names, ensuring that only valid, pre-defined atoms are created. This prevents denial-of-service attacks through atom table exhaustion.

Security

The BEAM VM has a fixed limit of approximately 1 million atoms. Creating atoms from untrusted user input can allow attackers to exhaust this limit and crash the VM.

This module uses whitelisting and String.to_existing_atom/1 to ensure:

  • Only supported locales can be converted to atoms
  • Only translatable fields can be converted to atoms
  • Invalid input is rejected with proper logging

Configuration

Configure supported locales in your application config:

config :ash_phoenix_translations,
  supported_locales: [:en, :es, :fr, :de, :it, :pt, :ja, :zh, :ko, :ar, :ru]

Examples

# Valid locale
iex> LocaleValidator.validate_locale("en")
{:ok, :en}

# Invalid locale
iex> LocaleValidator.validate_locale("invalid")
{:error, :invalid_locale}

# Valid field for resource
iex> LocaleValidator.validate_field("name", MyApp.Product)
{:ok, :name}

# Invalid field
iex> LocaleValidator.validate_field("nonexistent", MyApp.Product)
{:error, :invalid_field}

Summary

Functions

Returns the list of supported locales.

Validates a field name against translatable attributes for a resource.

Validates a locale and returns it as an atom if valid.

Functions

get_supported_locales()

Returns the list of supported locales.

Reads from application configuration, falling back to default locales.

validate_field(field, resource_module)

Validates a field name against translatable attributes for a resource.

Parameters

  • field - The field name to validate (atom or string)
  • resource_module - The Ash resource module to check against

Returns

  • {:ok, field_atom} if valid
  • {:error, :invalid_field} if invalid

Examples

validate_field("name", MyApp.Product)
#=> {:ok, :name}

validate_field("nonexistent", MyApp.Product)
#=> {:error, :invalid_field}

validate_locale(locale)

Validates a locale and returns it as an atom if valid.

Accepts both atoms and strings. For strings, validates against configured supported locales and only converts to existing atoms.

Parameters

  • locale - The locale to validate (atom or string)

Returns

  • {:ok, locale_atom} if valid
  • {:error, :invalid_locale} if invalid

Examples

validate_locale(:en)
#=> {:ok, :en}

validate_locale("es")
#=> {:ok, :es}

validate_locale("invalid")
#=> {:error, :invalid_locale}

validate_locale("<script>alert('xss')</script>")
#=> {:error, :invalid_locale}