CWE-183, Permissive List of Allowed Inputs, describes a protection mechanism built on a list of inputs allowed by policy because they are assumed safe. The list is too permissive: it admits an input that is not safe.
Allowlists are the recommended approach to input handling, so this one stings. It does not mean allowlists are wrong. It means an allowlist is only as good as the thought that went into each entry.
How it happens
Teams add entries to make features work. A class, a method, a file type or a command gets approved because it is convenient and looks harmless. Nobody revisits what that entry can do in combination with others.
MITRE's observed examples are from sandboxes and automation:
- CVE-2019-12799: a chain where an untrusted deserialization protection was bypassed by using an assumed trusted class.
- CVE-2019-10458: a sandbox bypass using a method that was on an allowlist. The same CVE is described for a CI/CD pipeline feature with unsafe elements in its allowlist, which let attackers get around script restrictions.
- CVE-2017-1000095: a sandbox bypass using unsafe methods that were on an allowlist.
A short illustration:
# Too permissive: allows any attribute on an "approved" module
ALLOWED_MODULES = {"os", "math", "json"}
def run(module, func, *args):
if module in ALLOWED_MODULES:
return getattr(__import__(module), func)(*args) # os.system is allowed
# Tighter: allow specific functions, not whole modules
ALLOWED = {("math", "sqrt"), ("json", "loads")}
def run(module, func, *args):
if (module, func) in ALLOWED:
return getattr(__import__(module), func)(*args)
What an attacker gains
MITRE lists access control impact: bypass of a protection mechanism. In the examples that translated to escaping a sandbox or running restricted scripts.
How to find it
MITRE says automated static analysis (SAST) can find some instances by following data flow through source or compiled code. Manual review of the list itself is just as useful. For each entry, ask what the worst thing is that it can do.
How to fix it
The record has no mitigations, so these are general steps.
- Allow the narrowest unit that does the job: a single function, not a whole library.
- Review every addition to the list as a security change.
- Remove entries nothing uses.
- Test the list by trying to chain entries together.
Quick check
Is the fix to abandon allowlists?
No. Keep them, but make each entry as narrow as possible and review them over time.