JustBash.BannedCallTracer (JustBash v0.4.0)
View SourceDetects banned remote function calls by inspecting compiled BEAM files.
Rather than re-compiling source, this module reads the abstract code
(debug info) from already-compiled .beam files and walks the call
tree looking for banned calls. No recompilation, no module-redefinition
warnings, no load-order problems.
Security model
JustBash code must never touch real system resources — all I/O goes through the virtual filesystem and environment abstractions. The banned categories are:
Filesystem (File, :file)
Any call into File.* or the Erlang :file module. Covers reads, writes,
stat, ls, exists?, mkdir, rm, etc.
Environment (System.get_env, System.put_env, System.delete_env)
Reading or mutating real OS environment variables.
Process / OS escape (System.cmd, System.shell, Port, :os, :erlang.open_port)
Spawning real OS processes or opening ports. These are the most dangerous — they can execute arbitrary host commands regardless of filesystem sandboxing.
Node escape (Node)
Connecting to or spawning processes on remote Erlang nodes.
Mutable shared state (Process.put/get/delete, :ets)
Process dictionary and ETS leak mutable state across calls, breaking referential transparency and making code unpredictable in concurrent use.
What this catches
- Direct calls:
File.read(path),System.cmd("rm", [...]) - Calls through Elixir aliases (resolved before compilation)
apply/3and:erlang.apply/3when both the module and function are literal atoms at the call site, e.g.apply(File, :read, [path])
What this cannot catch
Dynamic dispatch where the module or function is a runtime variable:
mod = File
mod.read(path) # module is a variable — opaque to static analysis
fun = :read
apply(File, fun, [path]) # function is a variable — opaqueThese cases require runtime instrumentation (e.g. :erlang.trace) to
detect. No purely static tool can catch them. The defense against dynamic
dispatch is code review discipline and the fact that there is no legitimate
reason for JustBash library code to hold a reference to File or System
in a variable at all.
Summary
Functions
Checks all .beam files under beam_dir for banned calls.
Returns a list of violations.
Checks a single .beam file for banned calls.
Types
@type violation() :: %{ call: {module(), atom(), arity()}, beam: Path.t(), line: non_neg_integer() }