domains / cloud-infra / pallets/flask
Robust environment config handling
Treat environment-variable driven configuration as untrusted, possibly malformed input, and handle it defensively and consistently. - Normalize and validate values read from the environment before use. Boolean-like flags (e.g. `FLASK_DEBUG`) must be compared case-insensitively and against a documented set of truthy/falsy strings, e.g. `val.lower() not in...
Treat environment-variable driven configuration as untrusted, possibly malformed input, and handle it defensively and consistently.
- Normalize and validate values read from the environment before use. Boolean-like flags (e.g.
FLASK_DEBUG) must be compared case-insensitively and against a documented set of truthy/falsy strings, e.g.val.lower() not in ('0', 'false', 'no')rather than listing every casing variant. - When parsing
.env/dotenv-style files, strip surrounding whitespace from keys and values, reject or skip malformed lines (missing=, multi-line values) instead of silently truncating them, and be careful with byte/str handling on Python 3 when the file is read in binary mode. - Enforce any stated scope/boundary for file discovery. If a function accepts a
top_dir(or similar) argument meant to limit how far up the directory tree it searches, verify with tests that it actually stops there — don’t rely oncommonprefixwithout checking directory containment correctly (preferos.path.commonpath-style comparison). - Access configuration values defensively. Prefer
current_app.debugorconfig.get('KEY', default)overconfig['KEY']so a missing or corrupted config doesn’t raise unexpectedly, unless the key is guaranteed to exist by framework invariants. - Clearly document which settings are intended to be controlled only through environment variables (e.g.
DEBUG,ENV) versus programmatically, and keep docstrings accurate about the actual runtime behavior (e.g. the debugger only activates when the debug env var/flag is set, not merely becauseapp.debugwas toggled in code).
Example of safer boolean parsing:
def get_debug_flag(default=None):
val = os.environ.get('FLASK_DEBUG')
if not val:
return default
return val.lower() not in ('0', 'false', 'no')
Applying these practices avoids subtle bugs where configuration behaves differently across casing, platforms, or directory contexts, and keeps environment-driven behavior predictable and well documented.