-
-
Notifications
You must be signed in to change notification settings - Fork 995
Add .well-known/security.txt file #2062
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
base: main
Are you sure you want to change the base?
Conversation
"The security.txt file is close to expiring. \ | ||
Please update the 'Expires' line in to confirm the contents are \ | ||
still accurate: {}".format( | ||
FILE_PATH | ||
), |
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.
'E501 line too long' is set up in this project (one that I generally disable) – any suggestions on how to clean this up?
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.
You could build the string outside of the assert method or shorten the message.
Is a test needed for this though? How about a calendar reminder? It seems like one day this will start failing the test suite on every PR/commit.
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.
Thanks for working on this Storm! 🎸
I've left a few minor stylistic comments inline, but I've also got some more general questions:
- I originally said that we could use an nginx config to link to the file, but after thinking about it some more I realized that it's going to be more complicated than I'd initially thought, because the
security.txt
is located inside the container. So I think a dedicated view is probably going to be better here. - Does the file need to be served under all subdomains (
www
,docs
,code
,dashboard
), or only some of them? - As Adam noted, I'm not sure a failing test is the right type of warning for this (though I appreciate that you thought about emitting a warning at all, that's good forward thinking). Did you explore other types of warnings for this and if so, could you walk us through what made you pick a test? On the top of my head, this could also potentially be a system check, a management command that we'd run regularly on the production server, or maybe even some kind of scheduled github action (I know django/django has some of those for example).
- edit: Oh, and also I think the folder should be named
well-known
: we don't need it to be hidden.
I'm happy to brainstorm or chat through things on Discord, or even on a call if you'd prefer. Just let me know.
Policy: https://www.djangoproject.com/security/ | ||
Contact: https://www.djangoproject.com/security/ | ||
Expires: 2026-12-31T00:00:00.000Z | ||
Encryption: https://keys.openpgp.org/vks/v1/by-fingerprint/AF3516D27D0621171E0CCE25FCB84B8D1D17F80B |
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.
For the sake of a future maintainer, it would be nice to document where one could find a link to the most up-to-date key. I was going to suggest a comment above this line, but I'm not sure if that's the best place for such documentation 🤔 (happy to hear other suggestions)
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.
I don't think this file might be a good place for putting that comment, since this file is targetted more towards people who want to report a security issue. It should ideally be there somewhere in a readme for contributors and maintainers. Maybe SECURITY.md (which I am planning on adding)?
|
||
# Hello security researcher! | ||
# We appreciate your help in keeping Django secure. | ||
# Please report security issues that concern the Django website (djangoproject.com) to ops@djangoproject.com |
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.
This seems to contradict the Policy
and Contact
directives above which state that one should email security@djangoproject.com
.
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.
I think we could change this with the website WG email: website-wg@djangoproject.com
to keep the security issues for Django itself separated for the fellows, but the security page need a new line somewhere to mention that security issues related to the website are supposed to be send to this email instead.
with open(FILE_PATH) as f: | ||
content = f.read() |
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.
Since we have a Path
object we can directly use:
with open(FILE_PATH) as f: | |
content = f.read() | |
content = FILE_PATH.read_text() |
(and remove a level of indentation for the rest of the method)
# Read the line that starts with "Expires:", and parse the date. | ||
for line in content.splitlines(): | ||
if line.startswith("Expires:"): | ||
expires = line.strip("Expires: ") | ||
break | ||
else: | ||
self.fail("No Expires line found in security.txt") |
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.
Perfect use of a for ... else
👏🏻 However I think a regex perfect for this kind of situation:
# Read the line that starts with "Expires:", and parse the date. | |
for line in content.splitlines(): | |
if line.startswith("Expires:"): | |
expires = line.strip("Expires: ") | |
break | |
else: | |
self.fail("No Expires line found in security.txt") | |
match = re.search("^Expires: (.*)$", content, flags=re.MULTILINE) | |
if match is None: | |
self.fail("No Expires line found in security.txt") | |
else: | |
expires = match[1] |
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.
TIL for ... else
. 🤯 🐍 ❤️
Thank you. 🫶
expires_date = datetime.strptime( | ||
expires, | ||
"%Y-%m-%dT%H:%M:%S.%fZ", | ||
).date() |
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.
You can use datetime.fromisoformat()
:
expires_date = datetime.strptime( | |
expires, | |
"%Y-%m-%dT%H:%M:%S.%fZ", | |
).date() | |
expires_date = datetime.fromisoformat(expires).date() | |
expires_date = datetime.strptime( | |
expires, | |
"%Y-%m-%dT%H:%M:%S.%fZ", | |
).date() |
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.
Looks good, thank you @Stormheg ! I added one comment for a small change, including the security page.
|
||
# Hello security researcher! | ||
# We appreciate your help in keeping Django secure. | ||
# Please report security issues that concern the Django website (djangoproject.com) to ops@djangoproject.com |
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.
I think we could change this with the website WG email: website-wg@djangoproject.com
to keep the security issues for Django itself separated for the fellows, but the security page need a new line somewhere to mention that security issues related to the website are supposed to be send to this email instead.
This is a PR for an action I took as member of the Website working group, see meeting notes here: https://forum.djangoproject.com/t/website-team-meeting-notes/40655
I spoke with @bmispelon yesterday during Wagtail Office Hours and he mentioned we can serve static files like this through a nginx rule which are controlled by the ops team. We apparently already do this for other 'static' content files. This has yet to be set up.
I chose to put this in a .well-known folder in the project root for visibility.
Consider the contents of the security.txt file an initial draft and open to discussion.