Opened 6 weeks ago
Closed 6 weeks ago
#35901 closed New feature (wontfix)
settings.DEBUG could reject non-empty string values (or in particular "off", "no", "0", "disabled", "false", "False")
Reported by: | Sebastian Pipping | Owned by: | |
---|---|---|---|
Component: | Core (Other) | Version: | dev |
Severity: | Normal | Keywords: | typed settings |
Cc: | Sebastian Pipping, Venkatesh S | Triage Stage: | Unreviewed |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Hi!
I came across a setup recently where (simplified) troubling code DEBUG = os.environ.get("DEBUG", False)
with environment variables state DEBUG=0
(and later DEBUG=False
) was activating Debug mode (while not intended to and and unaware of) in practice because these (and all other non-empty) strings evaluate to True
in Python:
In [1]: bool("") Out[1]: False In [2]: bool("False") Out[2]: True In [3]: bool("0") Out[3]: True
The related code is Open Source and my related pull request for their project is public at https://github.com/climateconnect/climateconnect/pull/1331 .
To cheaply protect users from accidents like these (that can easily result in arbitrary remote code execution) in the future, Django could reject values from settings.DEBUG
that are (a) any string or (b) any non-empty string or (c) in a list of known excluded words (e.g. "off", "no", "0", "disabled", "false", "False").
What do you think?
Change History (8)
comment:1 by , 6 weeks ago
comment:2 by , 6 weeks ago
Cc: | added |
---|---|
Resolution: | → invalid |
Status: | new → closed |
comment:3 by , 6 weeks ago
Resolution: | invalid |
---|---|
Status: | closed → new |
This is not about a specific setup but a pattern or I would not even create this ticket. Many users control debug mode through an environment variable and hopefully get this right like https://github.com/hartwork/jawanndenn/blob/356ee23f9b1bb3fa876e405a5b9fae0c0729e0df/jawanndenn/settings.py#L31 but reality proves that users could use help with this. Please re-consider just shutting me down. Thank you.
comment:4 by , 6 weeks ago
Has patch: | set |
---|
Pull request: https://github.com/django/django/pull/18793
comment:5 by , 6 weeks ago
I'd be inclined to say wontfix unless a consensus can be reached on the forum. See a related thread. on a proposal to add a system check to verify the type of all settings. There are often unintended side effects when we've added checks like this.
Here is an interesting approach (though perhaps not the best one) I found to help avoid a configuration mistake with environment variables:
from ast import literal_eval from os import getenv DEBUG = literal_eval(getenv('DEBUG', 'False'))
comment:6 by , 6 weeks ago
The code sample is a nice idea.
With regard to checking all setting types I don't see need to make the picture that big: the type check is an implemenation detail — we could as well just block values like `"off", "no", "0", "disabled", "false", "False" — but then the list will never be complete. The current explicit check also doesn't prevent any later migrations towards full blown type checks in the future. Why not start small?
I would appreciate to consider that this change alone would have saved unfortunate setup https://github.com/climateconnect/climateconnect/pull/1331 from potential remote code execution. That's the key motivator behind this suggestion: it could have been prevented easily.
comment:7 by , 6 weeks ago
Agreed with Tim. "wontfix" for me. This will definitely have side-effects on some projects.
comment:8 by , 6 weeks ago
Keywords: | typed settings added; security debug removed |
---|---|
Resolution: | → wontfix |
Status: | new → closed |
Type: | Uncategorized → New feature |
I agree with Tim and Mariusz that this proposal isn't suitable for Django (as a core feature). Moreover, I think it qualifies as a duplicate of #35231 (which is a ticket related to the forum link shared by Tim).
I'll close this as wontfix
because, if we were to implement a change that only applies to DEBUG
, it would be incomplete and inconsistent. Users would likely request similar handling for every boolean setting. Even if we made the behavior consistent, I don't believe this parsing logic belongs in the settings module. Django settings are meant to be Python files, and the core framework doesn't include functionality for reading from environment variables.
Another reason for closing as wontfix
is that there are third-party packages that handle parsing from env variables effectively. For example, django-environ uses BOOLEAN_TRUE_STRINGS = ('true', 'on', 'ok', 'y', 'yes', '1')
for bool logic parsing.
I think it's important to decouple the settings definition (the Python file where a string is not a bool) from reading settings from external sources, such as environment variables, INI config files, Puppetfiles, etc. The former definitely belongs to Django, while the latter is better suited for third-party packages or custom business logic.
Thank you, Sebastian, for reporting this and for your detailed explanation!
Our setup is handled this differently. However, I now see that, like many projects, it could indeed be affected by unintended string evaluations if values are drawn directly from .env files without parsing.
In our current Django configuration, we set DEBUG as a Boolean directly rather than retrieving it from .env, which avoids this specific issue for us.
Thank you!