Skip to content

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

Stormheg
Copy link
Member

@Stormheg Stormheg commented May 1, 2025

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.

@Stormheg Stormheg requested a review from bmispelon May 1, 2025 12:54
Comment on lines +200 to +204
"The security.txt file is close to expiring. \
Please update the 'Expires' line in to confirm the contents are \
still accurate: {}".format(
FILE_PATH
),
Copy link
Member Author

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?

Copy link
Member

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.

Copy link
Member

@bmispelon bmispelon left a 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:

  1. 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.
  2. Does the file need to be served under all subdomains (www, docs, code, dashboard), or only some of them?
  3. 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).
  4. 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
Copy link
Member

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)

Copy link
Contributor

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
Copy link
Member

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.

Copy link
Member

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.

Comment on lines +181 to +182
with open(FILE_PATH) as f:
content = f.read()
Copy link
Member

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:

Suggested change
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)

Comment on lines +183 to +189
# 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")
Copy link
Member

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:

Suggested change
# 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]

Copy link
Contributor

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. 🫶

Comment on lines +191 to +194
expires_date = datetime.strptime(
expires,
"%Y-%m-%dT%H:%M:%S.%fZ",
).date()
Copy link
Member

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():

Suggested change
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()

Copy link
Member

@sabderemane sabderemane left a 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
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants