{"id":32168411,"url":"https://github.com/functional-rewire/dune","last_synced_at":"2025-10-21T15:53:59.254Z","repository":{"id":57491956,"uuid":"408064277","full_name":"functional-rewire/dune","owner":"functional-rewire","description":"A sandbox for Elixir to safely evaluate untrusted code from user input","archived":false,"fork":false,"pushed_at":"2025-10-19T03:59:06.000Z","size":197,"stargazers_count":189,"open_issues_count":1,"forks_count":6,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-10-19T16:47:14.671Z","etag":null,"topics":["elixir","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/functional-rewire.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-09-19T07:43:49.000Z","updated_at":"2025-10-19T03:59:09.000Z","dependencies_parsed_at":"2023-11-10T12:51:36.937Z","dependency_job_id":"4d32190f-45f2-4f94-9d6b-f6aff6e93d0a","html_url":"https://github.com/functional-rewire/dune","commit_stats":{"total_commits":57,"total_committers":1,"mean_commits":57.0,"dds":0.0,"last_synced_commit":"14d687e72b87973c21c36dae58139ad36561fa7e"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/functional-rewire/dune","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/functional-rewire%2Fdune","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/functional-rewire%2Fdune/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/functional-rewire%2Fdune/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/functional-rewire%2Fdune/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/functional-rewire","download_url":"https://codeload.github.com/functional-rewire/dune/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/functional-rewire%2Fdune/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280196632,"owners_count":26288905,"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-10-21T02:00:06.614Z","response_time":58,"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","sandbox"],"created_at":"2025-10-21T15:53:55.900Z","updated_at":"2025-10-21T15:53:59.244Z","avatar_url":"https://github.com/functional-rewire.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dune\n\n[![Hex Version](https://img.shields.io/hexpm/v/dune.svg)](https://hex.pm/packages/dune)\n[![docs](https://img.shields.io/badge/docs-hexpm-blue.svg)](https://hexdocs.pm/dune/)\n[![CI](https://github.com/functional-rewire/dune/workflows/CI/badge.svg)](https://github.com/functional-rewire/dune/actions?query=workflow%3ACI)\n\nA sandbox for Elixir to safely evaluate untrusted code from user input.\n\n[**Try it out on our online playground!**](https://playground.functional-rewire.com/)\n\n`Dune` can be useful to develop playgrounds, online REPL, coding games, or\ncustomizable business logic.\n\n**Warning:** `Dune` cannot offer strong security guarantees (see the\n[Security guarantees](#security-guarantees) section below). Besides, it is still\nearly stage: expect bugs and vulnerabilities.\n\n## Features\n\n- allowlist mechanism (customizable) to restrict execution to safe modules and\n  functions: no access to environment variables, file system, network...\n- code executed in an isolated process\n- execution within configurable limits: timeout, maximum reductions and memory\n  (inspired by [Luerl](https://github.com/rvirding/luerl))\n- captured standard output\n- atoms, without atom leaks: parsing and runtime do not\n  [leak atoms](https://hexdocs.pm/elixir/String.html#to_atom/1) (i.e. does not\n  keep\n  [filling the atom table](https://learnyousomeerlang.com/starting-out-for-real#atoms)\n  until the VM crashes)\n- modules, without actual module creation: Dune does not let users define any\n  actual module (would leak memory and modify the state of the VM globally), but\n  `defmodule` simulates the basic behavior of a module, including private and\n  recursive functions\n\n```elixir\niex\u003e Dune.eval_string(\"IO.puts(\\\"Hello world!\\\")\")\n%Dune.Success{inspected: \":ok\", stdio: \"Hello world!\\n\", value: :ok}\n\niex\u003e Dune.eval_string(\"File.cwd!()\")\n%Dune.Failure{message: \"** (DuneRestrictedError) function File.cwd!/0 is restricted\", type: :restricted}\n\niex\u003e Dune.eval_string(\"List.duplicate(:spam, 100_000)\")\n%Dune.Failure{message: \"Execution stopped - memory limit exceeded\", stdio: \"\", type: :memory}\n\niex\u003e Dune.eval_string(\"Enum.product(1..100_000)\")\n%Dune.Failure{message: \"Execution stopped - reductions limit exceeded\", stdio: \"\", type: :reductions}\n```\n\nThe list of modules and functions authorized by default is defined by the\n[`Dune.Allowlist.Default`](https://hexdocs.pm/dune/Dune.Allowlist.Default.html#module-allowed-modules-functions)\nmodule, but this list can be extended and customized (at your own risk!) using\n[`Dune.Allowlist`](https://hexdocs.pm/dune/Dune.Allowlist.html).\n\nIf you need to keep the state between evaluations, you might consider\n[`Dune.Session`](https://hexdocs.pm/dune/Dune.Session.html):\n\n```elixir\niex\u003e Dune.Session.new()\n...\u003e |\u003e Dune.Session.eval_string(\"x = 1\")\n...\u003e |\u003e Dune.Session.eval_string(\"x + 2\")\n#Dune.Session\u003clast_result: %Dune.Success{inspected: \"3\", stdio: \"\", value: 3}, ...\u003e\n```\n\n`Dune.string_to_quoted/2` returns the AST corresponding to the provided\n`string`, without leaking atoms:\n\n```elixir\niex\u003e Dune.string_to_quoted(\"foo(:bar)\").inspected\n\"{:foo, [line: 1], [:bar]}\"\n```\n\n## Limitations\n\n`Dune` supports a fair subset of the base language, but it cannot safely support\nadvanced features (at least at this stage) such as:\n\n- custom structs / behaviours / protocols\n- concurrency / processes / OTP\n- metaprogramming\n\n## Security guarantees\n\nBecause of the approch being used, Dune cannot offer strong security guarantees,\nand should not be considered a sufficient security layer by itself.\n\nA best-effort approach is made to prevent attackers from getting outside of the\noriginal process and from calling any function/macro outside of the allowlist.\nHowever, it is impossible to prove that all escape paths have been completely\nblocked. Due to how the Erlang VM works, an attacker able to escape the sandbox\ncould get full access to the VM without restriction.\n\nSee the\n[EEF guidelines about sandboxing](https://erlef.github.io/security-wg/secure_coding_and_deployment_hardening/sandboxing)\nfor more information.\n\nUse at your own risk and avoid running it directly on a server with any\nsensitive access, e.g. to a database.\n\n## Installation\n\nThe package can be installed by adding `dune` to your list of dependencies in\n`mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:dune, \"~\u003e 0.3.15\"}\n  ]\nend\n```\n\nDocumentation can be found at\n[https://hexdocs.pm/dune](https://hexdocs.pm/dune).\n\n## FAQ\n\n### Why can I still create atoms?\n\nAtoms are converted by the parser and mapped to always use a given set of atoms.\nSo when you type `foo = bar(:baz)`, the atoms `:foo`, `:bar` and `:baz` won't\nactually be created, but other atoms like `:atom1`, `:atom2` and `:atom3` are\ngoing to be used instead.\n\nSo even if many user run various codes using many different variable and\nfunction names, they will all pull from the same pool of atoms.\n\n### Why can I still create modules?\n\nModules are being defined globally within the VM, making it both an isolation\nconcern and a memory concern. But modules are an important part of the Elixir\nlanguage, and are especially important for learning platforms.\n\nDune implements an alternative `defmodule`, relying on maps of anonymous\nfunctions at runtime and should reproduce the basic behavior of actual modules,\nwith support for recursive and private functions.\n\n### Why is the behavior different than Elixir when doing X?\n\nAs explained above, some parts of the language are actually being completely\nreimplemented because the original version could not be safely sandboxed: atoms,\nmodules... While these alternative implementation aim to be as close as possible\nto the original ones, they might differ in some cases, because the code being\nexecuted is actually different.\n\n### Why can't I do X?\n\nSome parts of the language are being restricted because they present a direct\nsecurity risk, while some other would need to be reimplemented in an alternative\nway and therefore need a consequent amount of work that hasn't been done yet.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffunctional-rewire%2Fdune","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffunctional-rewire%2Fdune","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffunctional-rewire%2Fdune/lists"}