Unintended public API exposure due to export_all: what safeguards exist?
0 reputation · 04 Nov 2022, 13:08 UTC
0 reputation · 04 Nov 2022, 13:08 UTC
In Erlang modules, the -export/1 clause defines the public API. Using -export_all can inadvertently expose internal helper functions, especially when combined with OTP behaviours that rely on exported callbacks. This can lead to unintended remote calls or misuse.
The community has documented that omitting functions from the export list prevents accidental exposure, but there is no built‑in role‑based control. OTP behaviours such as gen_server expect specific exported callbacks, yet they do not enforce minimal export beyond the required ones.
We need to understand what compile‑time or runtime mechanisms exist to detect or prevent accidental export of internal functions, and how to enforce stricter boundaries within OTP applications.
33275 reputation · 04 Nov 2022, 20:01 UTC
The Erlang compiler does not provide a specific flag to automatically detect functions that are exported but not referenced by an OTP behaviour or external module. Because -export_all explicitly tells the compiler to make every function public, the compiler assumes this is intentional behavior.
While there is no single "strict mode" for exports, the following mechanisms are used to identify and prevent accidental exposure:
-W flag during compilation allows the compiler to emit warnings for unused functions. However, this is a general check and does not specifically distinguish between a function that should be private and one that is a valid but currently unused public API.gen_server) only ensure that the required callbacks are exported; they do not restrict the module from exporting additional, unintended functions.To enforce stricter boundaries and avoid the risks of -export_all, use these established patterns:
| Pattern | Implementation | Verification |
|---|---|---|
| Explicit Export List | Replace -export_all with -export([func1/1, func2/2]). |
Manual review of the export list against the behaviour's behaviour_info/2. |
| Internal Modules | Move helper functions to a separate module (e.g., my_app_internal.erl). |
Ensure the internal module is not listed as a public API in documentation or wrapper modules. |
| Opaque Data Types | Define records in a separate header file and do not export the record fields. | Dialyzer will flag attempts to access private record fields from external modules. |
To audit your current application for accidental exposures, run the following:
erlc -W my_module.erl.-export_all is absent from all production modules.Diagnostic Detail Needed: Do you currently enable compiler warnings (-W) in your CI/CD pipeline? If not, Dialyzer is your only automated line of defense for this specific issue.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.