{"id":30524907,"url":"https://github.com/sequinstream/mini_elixir","last_synced_at":"2025-10-19T17:16:55.974Z","repository":{"id":311658001,"uuid":"1030450464","full_name":"sequinstream/mini_elixir","owner":"sequinstream","description":"Elixir code sandbox with AST validation and an allowlist for running untrusted code.","archived":false,"fork":false,"pushed_at":"2025-08-25T19:05:24.000Z","size":25,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-25T20:46:06.642Z","etag":null,"topics":["elixir","safe-evaluation","sandbox"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sequinstream.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-01T16:57:16.000Z","updated_at":"2025-08-25T18:55:13.000Z","dependencies_parsed_at":"2025-08-25T20:46:08.336Z","dependency_job_id":"f287bc82-021b-44b7-870c-41b2874935c6","html_url":"https://github.com/sequinstream/mini_elixir","commit_stats":null,"previous_names":["sequinstream/mini_elixir"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/sequinstream/mini_elixir","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequinstream%2Fmini_elixir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequinstream%2Fmini_elixir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequinstream%2Fmini_elixir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequinstream%2Fmini_elixir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sequinstream","download_url":"https://codeload.github.com/sequinstream/mini_elixir/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequinstream%2Fmini_elixir/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272255757,"owners_count":24901322,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-26T02:00:07.904Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elixir","safe-evaluation","sandbox"],"created_at":"2025-08-26T21:02:40.060Z","updated_at":"2025-10-19T17:16:55.876Z","avatar_url":"https://github.com/sequinstream.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MiniElixir\n\nMiniElixir provides a safe sandbox for evaluating Elixir code with restricted functionality. It allows users to write and execute Elixir code in a controlled environment where only whitelisted functions and operators are available.\n\n## Benchmarks\n\nRun:\n\n```bash\nmix run bench/transform_bench.exs\n```\n\nExample results:\n\n```\nName                                                    ips        average  deviation         median         99th %\nNative                                               1.14 M      876.13 ns  ±2452.00%         750 ns        1083 ns\nMiniElixir.eval/5 persistent: true (hot call)        1.02 M      979.19 ns  ±1911.87%         833 ns        1666 ns\nMiniElixir.eval/5 persistent: false               0.00016 M  6153605.28 ns     ±5.47%     6123417 ns  6954676.86 ns\n\nComparison:\nNative                                               1.14 M\nMiniElixir.eval/5 persistent: true (hot call)        1.02 M - 1.12x slower +103.06 ns\nMiniElixir.eval/5 persistent: false               0.00016 M - 7023.61x slower +6152729.14 ns\n```\n\n## Status \u0026 Security\n\n\u003e ⚠️ **Alpha Status**: This library is not ready for production. APIs and validation rules may change. Use at your own risk.\n\nIf you encounter any security issues or potential vulnerabilities, **please create an issue** in the GitHub repository:\n\n- Issues: [github.com/sequinstream/mini_elixir/issues](https://github.com/sequinstream/mini_elixir/issues)\n\n## Features\n\n- Safe evaluation of Elixir code strings\n- Restricted access to only whitelisted functions and operators\n- Protection against dangerous operations\n- Support for any module and function name\n- Automatic cleanup after execution\n\n## Installation\n\nAdd `mini_elixir` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:mini_elixir, \"~\u003e 0.1.0\"}\n  ]\nend\n```\n\n## Usage\n\nMiniElixir allows you to safely evaluate Elixir code strings that define modules with functions. The module is automatically created, executed, and cleaned up after each evaluation.\n\n### Basic Example\n\n```elixir\ncode = \"\"\"\ndefmodule Calculator do\n  def add_tax(price) do\n    tax = price * 0.2\n    %{price: price, tax: tax, total: price + tax}\n  end\nend\n\"\"\"\n\n{:ok, result} = MiniElixir.eval(code, Calculator, :add_tax, [100.0])\n# result = %{price: 100.0, tax: 20.0, total: 120.0}\n```\n\n### String Processing Example\n\n```elixir\ncode = \"\"\"\ndefmodule NameFormatter do\n  def format_name(first, last) do\n    String.trim(\"#{String.capitalize(first)} #{String.capitalize(last)}\")\n  end\nend\n\"\"\"\n\n{:ok, result} = MiniElixir.eval(code, NameFormatter, :format_name, [\"john\", \"doe\"])\n# result = \"John Doe\"\n```\n\n### Complex Data Processing Example\n\n```elixir\ncode = \"\"\"\ndefmodule ListProcessor do\n  def process_list(items) do\n    items\n    |\u003e Enum.map(\u0026String.upcase/1)\n    |\u003e Enum.sort()\n    |\u003e Enum.with_index(1)\n    |\u003e Map.new(fn {item, idx} -\u003e {idx, item} end)\n  end\nend\n\"\"\"\n\n{:ok, result} = MiniElixir.eval(code, ListProcessor, :process_list, [[\"banana\", \"apple\", \"cherry\"]])\n# result = %{1 =\u003e \"APPLE\", 2 =\u003e \"BANANA\", 3 =\u003e \"CHERRY\"}\n```\n\n## API Reference\n\n### `MiniElixir.eval/5`\n\nEvaluates a string of Elixir code in a safe sandbox environment.\n\n```elixir\nMiniElixir.eval(code, module, function, args, opts \\\\ [persistent: true]) :: {:ok, result} | {:error, reason}\n```\n\n#### Parameters\n\n- `code` (string): Elixir code string containing a module definition\n- `module` (atom): The module name to define the function in\n- `function` (atom): The name of the function to define and call\n- `args` (list): List of arguments to pass to the function\n- `opts` (keyword): Options\n  - `:persistent` (boolean, default: `true`): when true, the module is kept loaded and reused on subsequent calls; when false, the module is purged/deleted after the call\n\n#### Returns\n\n- `{:ok, result}` on success\n- `{:error, reason}` on failure\n\n## Allowed vs Disallowed\n\nMiniElixir validates code before it is compiled/executed. Only a specific set of operators and modules are allowed. Anything not listed is rejected during validation.\n\n### Allowed operators\n- Arithmetic: `+`, `-`, `*`, `/`\n- Comparison: `==`, `!=`, `===`, `!==`, `\u003e`, `\u003e=`, `\u003c`, `\u003c=`\n- Logical: `\u0026\u0026`, `||`, `and`, `or`, `not`\n- String concatenation: `\u003c\u003e`\n- List concatenation: `++`\n- Pipe: `|\u003e`\n- List cons and map update: `|` (e.g., `[h | t]`, `%{map | key: v}`)\n- Access/tuple/bitstring/guards: `.`, `{}`, `\u003c\u003c\u003e\u003e`, `::`, `when`, `-\u003e`, `fn`, `__block__`\n\n### Allowed modules and calls\n- Kernel:\n  - Guards: selected guards (e.g., `is_integer/1`, `is_binary/1`, ...)\n  - Functions: selected functions (e.g., `abs/1`, `to_string/1`, ...)\n- Kernel sigils: `~C ~D ~N ~R ~S ~T ~U ~c ~r ~s ~w`\n- Access: `Access.get/2`\n- Map: all functions\n- String: all except `String.to_atom/1` and `String.to_existing_atom/1`\n- Enum: all functions\n- Date, DateTime, NaiveDateTime: all functions\n- Decimal: all functions\n- URI, Base, UUID, JSON, Integer, Regex, Eden, List: all functions\n- Local function calls: calling a function by name (e.g., recursion) is allowed\n- Calling through function arguments: allowed (e.g., `record[:id]`, `changes[\"foo\"]`)\n\n### Disallowed (examples; anything not in the allowed list is blocked)\n- Filesystem: `File.read!/1`, `File.write/2`, etc.\n- I/O and OS: `IO.puts/1`, `System.cmd/2`, `:os.cmd/1`, `Port`, `:erlang` internals\n- Code loading/eval: `Code.eval_string/1`, dynamic module creation inside the function\n- Network/process: `:rpc`, `GenServer`, `Task`, `Process`, `Application`\n- Atom creation from strings: `String.to_atom/1`, `String.to_existing_atom/1`\n- Defining modules or functions inside the validated body: `defmodule`, `def`, `defp`\n\nWhy a call is blocked: the validator resolves the call path (e.g., `File.read!(path)` → `File.read!`) and rejects it if the module/function isn’t on the allowlist, returning an error like `Forbidden function: File.read!`.\n\n## Contributing\n\nContributions are more than welcome. Useful areas include:\n\n- **Testing**: Add unit tests and edge cases; consider property-based tests (e.g., `stream_data`) or fuzzing for the validator and transformer.\n- **Performance**: Profile and optimize hot paths; extend `bench/transform_bench.exs`; include before/after numbers in PRs where relevant.\n- **Security**: Review the allowlist, harden validation, add negative tests, and propose threat-model updates. For suspected vulnerabilities, open an issue rather than sharing public PoCs.\n- **Documentation**: Improve the README and API docs; add short guides.\n- **Examples**: Provide practical code samples and usage recipes.\n\n### How to contribute\n\n1. Fork the repository and create a feature branch.\n2. Run tests locally: `mix test`.\n3. Open a PR with a concise description and, if applicable, benchmarks or security rationale.\n\nQuestions or proposals:\n\n- Issues: [github.com/sequinstream/mini_elixir/issues](https://github.com/sequinstream/mini_elixir/issues)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsequinstream%2Fmini_elixir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsequinstream%2Fmini_elixir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsequinstream%2Fmini_elixir/lists"}