-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix issue that occurs when using bytes as secret key. #890
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Current coverage is 76.72% (diff: 100%)@@ master #890 diff @@
==========================================
Files 30 30
Lines 1653 1654 +1
Methods 0 0
Messages 0 0
Branches 245 245
==========================================
+ Hits 1268 1269 +1
Misses 311 311
Partials 74 74
|
I don't think that The default, empty value is https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-SECRET_KEY doesn't say anything about If you look at the implementation of In a 12-factor app it's a best practice to provide secrets via environment variables and random bytes (half of which are non-ASCII) aren't safe to pass via environment variables. That said, it's best not to crash when SECRET_KEY contains I don't see the point of randomizing the SECRET_KEY in the tests setting, what problem is this solving? |
There is no default value for SECRET_KEY. If it's left out, Django will throw an error stating the SECRET_KEY is not set. Most of the code that requires the SECRET_KEY use it in methods that only accept it as bytes. For example, see django.utils.crypto (https://github.com/django/django/blob/master/django/utils/crypto.py). Setting the secret key shouldn't be limited to setting them via environment variables. In any case, the script has to fetch the SECRET_KEY from somewhere before placing it in an environment variable. As for why I changed the SECRET_KEY in the tests, I found that changing the key was the best way to verify make_hash still works. Leaving out the changes to make_hash and setting the SECRET_KEY to a non-UTF-8 byte string would cause the tests to fail. Placing the changes to make_hash and SECRET_KEY causes all tests to pass without modification. |
Was there any concern still about this change? |
I don't see any explanation for the removal of the newline normalization. Maybe there's a good reason for that and I don't see it? Please explain. Moving from force_text to force_bytes is certainly the right thing to do since hashlib expects bytes, and I agree that the crash should be fixed, even though I've never seen a SECRET_KEY consisting of bytes in the wild until now. |
I must ask, why was the input to the hash being modified in the first place? Note that replacing newlines with spaces gives you different hashes. For example... In [1]: import hashlib In [2]: hashlib.sha1(b'some long string').hexdigest() In [3]: hashlib.sha1(b'some\nlong\nstring').hexdigest() |
The Django secret key can and should be random bytes which may or may not be decodable to UTF-8.
The idea probably was that the SQL query would pass through a textarea or something where newlines might be changed from I've been thinking a bit, and modifying queries in the browser does not and should not work anyway. So I'm good with this change. |
Can we just remove the randomization of the secret key in tests? I really dislike randomness in tests, no matter the reason (except, of course, when testing a statistical process or something that explicitly deals with randomness). I thought I said that earlier but I can't find that comment 😕 |
The new secret key is not random at all. It's a byte string of bytes with values 0 through 255 in sorted order. |
Here is what that secret key is now.
|
Ah, right, I had missed that change in your patch. However, like I explained at length earlier, putting bytes in the SECRET_KEY still goes against Django's expectations and established practice. There's even a ticket about it: https://code.djangoproject.com/ticket/24994. The changes to the test settings in this PR are not only useless but also wrong. |
@@ -7,7 +7,7 @@ | |||
|
|||
# Quick-start development settings - unsuitable for production | |||
|
|||
SECRET_KEY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Revert this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check the ticket you linked again (https://code.djangoproject.com/ticket/24994). They've closed the ticket without making any changes, referencing a comment I left to them (see django/django#7510).
Also note, the Django docs already recommended the use of external files for storing the SECRET_KEY, in which case it's reasonable to expect the SECRET_KEY be bytes, given the multiple ways files can be opened in Python (as bytes). See https://docs.djangoproject.com/en/stable/howto/deployment/checklist/#secret-key .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
open
defaults to reading in text mode, which means that the snippet from the documentation returns text, not binary, which negates your point.
I can see the case for putting bytes in SECRET_KEY, especially now that the system check PR in Django has been closed. OTOH as Aymeric said it's not established practice, so please try submitting a documentation patch to Django saying bytes as SECRET_KEY is supported, and maybe even recommended. I don't see why DDT has to move first (especially since, with the rest of your changes, your use case will work perfectly).
Thanks!
I went ahead and merged your change with an added commit that reverts the Thanks for your contribution! |
The Django secret key can and should be random bytes which may or may
not be decodable to UTF-8.