Packages

Production-ready hyperparameter optimization for Elixir with high Optuna parity. Leverages BEAM fault tolerance, real-time dashboards, and native distributed computing.

Current section

Files

Jump to
scout lib util safe_atoms.ex
Raw

lib/util/safe_atoms.ex

defmodule Scout.Util.SafeAtoms do
@moduledoc """
Security hardening: prevent atom table exhaustion and RCE via String.to_atom/1.
Only allows whitelisted atoms from user input.
"""
@valid_goals ~w(maximize minimize)a
@valid_samplers ~w(random tpe bandit grid)a
@valid_pruners ~w(median hyperband successive_halving)a
@valid_statuses ~w(pending running completed failed pruned)a
@goal_map %{
"maximize" => :maximize,
"minimize" => :minimize
}
@sampler_map %{
"random" => :random,
"tpe" => :tpe,
"bandit" => :bandit,
"grid" => :grid
}
@pruner_map %{
"median" => :median,
"hyperband" => :hyperband,
"successive_halving" => :successive_halving,
"sha" => :successive_halving # alias
}
@status_map %{
"pending" => :pending,
"running" => :running,
"completed" => :completed,
"failed" => :failed,
"pruned" => :pruned
}
@spec goal_from_string!(String.t()) :: :maximize | :minimize
def goal_from_string!(s) when is_binary(s) do
case Map.fetch(@goal_map, String.downcase(s)) do
{:ok, atom} -> atom
:error -> raise ArgumentError, "unsupported goal: #{inspect(s)}. Valid: #{Map.keys(@goal_map)}"
end
end
@spec sampler_from_string!(String.t()) :: atom()
def sampler_from_string!(s) when is_binary(s) do
case Map.fetch(@sampler_map, String.downcase(s)) do
{:ok, atom} -> atom
:error -> raise ArgumentError, "unsupported sampler: #{inspect(s)}. Valid: #{Map.keys(@sampler_map)}"
end
end
@spec pruner_from_string!(String.t()) :: atom()
def pruner_from_string!(s) when is_binary(s) do
case Map.fetch(@pruner_map, String.downcase(s)) do
{:ok, atom} -> atom
:error -> raise ArgumentError, "unsupported pruner: #{inspect(s)}. Valid: #{Map.keys(@pruner_map)}"
end
end
@spec status_from_string!(String.t()) :: atom()
def status_from_string!(s) when is_binary(s) do
case Map.fetch(@status_map, String.downcase(s)) do
{:ok, atom} -> atom
:error -> raise ArgumentError, "unsupported status: #{inspect(s)}. Valid: #{Map.keys(@status_map)}"
end
end
@doc "Get all valid atoms for a category"
def valid_goals, do: @valid_goals
def valid_samplers, do: @valid_samplers
def valid_pruners, do: @valid_pruners
def valid_statuses, do: @valid_statuses
end