Heuristic:Trailofbits Fickling Allowlist Maintenance
| Knowledge Sources | |
|---|---|
| Domains | Security, ML_Safety |
| Last Updated | 2026-02-14 13:00 GMT |
Overview
Best practices for using the `also_allow` parameter to extend fickling's ML allowlist with custom imports while maintaining security guarantees.
Description
Fickling's ML allowlist (`ML_ALLOWLIST`) is a curated dictionary of imports considered safe during pickle deserialization. When a model requires imports not in the default allowlist, users can extend it via `also_allow`. However, adding imports carelessly can negate fickling's security protections entirely. This heuristic captures the rules and reasoning for safe allowlist extension.
Usage
Use this heuristic when fickling raises `UnsafeFileError` on a model you trust, and you need to allow specific additional imports. This is common when loading models from frameworks not yet covered by the default allowlist (e.g., custom training frameworks, newer library versions with renamed modules).
The Insight (Rule of Thumb)
- Action: Use `also_allow` to add specific fully-qualified import paths (e.g., `"mylib.module.ClassName"`), never entire modules.
- Value: Each entry in `also_allow` must be in `"module.name"` format — the last dot-separated segment is the name, everything before it is the module.
- Trade-off: Every additional allowed import is a potential attack vector. The more imports you allow, the weaker the protection.
- Rule: Never allow imports from modules that can execute arbitrary code: `os`, `subprocess`, `sys`, `builtins`, `eval`, `exec`, `shutil`, `socket`, `pickle`, `_pickle`, `code`, `pty`.
- Process: If unsure whether an import is safe, open a GitHub issue on fickling for the Trail of Bits team to review and potentially include it in the default allowlist.
Reasoning
The `also_allow` parameter works by extending the internal allowlist dictionary. The `FicklingMLUnpickler.find_class()` method checks every import against this allowlist — if the module is missing or the name within the module is not listed, it raises `UnsafeFileError`. The allowlist is the sole security boundary during ML unpickling.
Each allowlist entry in the default `ML_ALLOWLIST` includes a safety justification message explaining why the import is considered safe (e.g., "This class is callable but the call redirects to __new__ which just builds a new object"). When adding custom imports, users should apply the same reasoning: verify the import cannot be used as a code execution, `getattr`, or file I/O primitive.
Code evidence from `fickling/ml.py:341-351`:
class FicklingMLUnpickler(pickle.Unpickler):
def __init__(self, *args, also_allow: list[str] | None = None, **kwargs):
self.allowlist = dict(ML_ALLOWLIST)
super().__init__(*args, **kwargs)
# Add additional allowed imports
if also_allow:
for allowed_import in also_allow:
module, name = allowed_import.rsplit(".", 1)
if module in self.allowlist:
self.allowlist[module][name] = "Import explicitly allowed by user"
else:
self.allowlist[module] = {name: "Import explicitly allowed by user"}
README warning from `README.md:76`:
Important: You should always make sure that manually added imports are actually safe and can not enable attackers to execute arbitrary code. If you are unsure on how to do that, you can open an issue on Fickling's Github repository.