# Adding CSP support to Django

**URL:** <https://forum.djangoproject.com/t/adding-csp-support-to-django/31526>\
**Category:** Django Internals\
**Created:** [May 26, 2024, 4:24pm UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526 "2024-05-26T16:24:34Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![robhudson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/robhudson/32/18764_2.png) [@robhudson](https://forum.djangoproject.com/u/robhudson)\
**Post date:** [May 26, 2024, 4:24pm UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/1 "2024-05-26T16:24:34Z")

</div>

Hi everyone,

I’m writing to express interest in adding CSP support to Django. The motivation behind this is to provide built-in support for Content Security Policy (CSP), a crucial security feature that helps mitigate a range of attacks such as Cross-Site Scripting (XSS) and data injection attacks.

There’s a Django bug for this:  
[https://code.djangoproject.com/ticket/15727](https://code.djangoproject.com/ticket/15727)

I have reviewed previous discussions and seen several PRs that never quite made it over the finish line. The general consensus seems to be that most people agree this would be beneficial for Django, although there’s some disagreement on some of the finer details. I’m hoping to spark discussion on those and find consensus.

As the current maintainer of django-csp, I have a good understanding of its strengths and areas for improvement. While I don’t think django-csp should be copied verbatim, I’m willing to adapt the good parts to fit Django standards. I’d love it if this could make it into Django 5.2, and alongside this, I’d like django-csp 4.0 to match the configuration style. This way, it would serve as a good third-party package for those not yet on Django 5.2, while also minimizing the work required to upgrade.

I have initiated a branch if you’d like to see the current direction, but wanted to share my intention here before creating a draft PR to get some general feedback and gauge interest. The branch includes several “TODO” comments on areas I consider open for discussion, which would be easier to comment on once a draft PR is published:

> **[Comparing django:main...robhudson:add-csp · django/django](https://github.com/django/django/compare/main...robhudson:django:add-csp)**
>
> The Web framework for perfectionists with deadlines. - Comparing django:main...robhudson:add-csp · django/django

Looking forward to your thoughts and collaboration.

Best regards,  
Rob

---

<div class="post-metadata">

**Author:** ![benjaoming](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/benjaoming/32/11815_2.png) [@benjaoming](https://forum.djangoproject.com/u/benjaoming)\
**Post date:** [May 30, 2024, 8:47am UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/2 "2024-05-30T08:47:33Z")

</div>

> I have reviewed previous discussions and seen several PRs that never quite made it over the finish line. The general consensus seems to be that most people agree this would be beneficial for Django, although there’s some disagreement on some of the finer details.

Would you mind referencing these discussions? Just so that curious people can read up before responding 🙂

I’ll gladly admit that CSP often slips my mind in projects, simply because Django provides lots of security, so it’s easy to get lazy and assume that it’s all taken care of. I think I’ve mostly added it in Nginx, but maybe also with django-csp in the earlier days.

It would seem like - no matter the outcome of this discussion - the [Django Docs topic on Security](https://docs.djangoproject.com/en/5.0/topics/security/) could have a section on CSP.

Edit: Now proposed some documentation: [Docs: Add CSP to Security topic by benjaoming · Pull Request #18212 · django/django · GitHub](https://github.com/django/django/pull/18212)

---

<div class="post-metadata">

**Author:** ![robhudson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/robhudson/32/18764_2.png) [@robhudson](https://forum.djangoproject.com/u/robhudson)\
**Post date:** [May 30, 2024, 9:41pm UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/3 "2024-05-30T21:41:05Z")

</div>

> [@benjaoming](#):
>
> Would you mind referencing these discussions? Just so that curious people can read up before responding 🙂

Sure! There may be others but this is what I could find again from browser history…

django-developers list:  
A comment from James Bennett, “Content Security Policy support in core. The current django-csp third-party app isn’t necessarily bad, but I’d love to see more good security tools in Django by default.” referenced [here](https://groups.google.com/g/django-developers/c/0lelyphIw8k/m/tKnbQ24TCQAJ)

PR from 2014:

> <https://github.com/django/django/pull/3550>

PR from 2015:

> <https://github.com/django/django/pull/5776>
>
> This is copied from https://github.com/mozilla/django-csp
> 
> It's licensed under t…he MPL, but that's compatible with BSD https://www.mozilla.org/en-US/MPL/2.0/FAQ/#mpl-bsd-and-apache
> 
> pinging @jsocol who last committed to the project

PR from 2023:

> <https://github.com/django/django/pull/16864>
>
> Added support for Content Security Policy(CSP) to SecurityMiddleware. It is stil…l a WIP and I haven't added system checks yet. Please provide suggestions. 😄

I think I’ll create my own draft PR for my branch now to make it easier to discuss.

---

<div class="post-metadata">

**Author:** ![GitRon](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/gitron/32/13088_2.png) [@GitRon](https://forum.djangoproject.com/u/GitRon)\
**Post date:** [July 1, 2024, 1:37pm UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/4 "2024-07-01T13:37:23Z")

</div>

Hi @robhudson

really cool that you picked that up. I’m wondering why Adam Johnson didn’t yet jump on this train. If I remember correctly, he argued in favour of this at DjangoCon Europe 2018.

If we add something like this, I’m wondering if we should make Django compliant as well. AFAIK there is an issue with the admin that you have to have `unsafe-inline` to be set, otherwise some features don’t work. I couldn’t reproduce it on the fly. Does anybody know more about that?

Best from Cologne  
Ronny

---

<div class="post-metadata">

**Author:** ![robhudson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/robhudson/32/18764_2.png) [@robhudson](https://forum.djangoproject.com/u/robhudson)\
**Post date:** [July 1, 2024, 3:03pm UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/5 "2024-07-01T15:03:54Z")

</div>

Hi @GitRon ,

I believe the `unsafe-inline`s in the Django admin were fixed. Here’s the closed bug about that: [#25165 (Move JavaScript calls out of HTML to fix JavaScript "no-script-eval" warnings) – Django](https://code.djangoproject.com/ticket/25165)

Cheers!  
-Rob

---

<div class="post-metadata">

**Author:** ![GitRon](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/gitron/32/13088_2.png) [@GitRon](https://forum.djangoproject.com/u/GitRon)\
**Post date:** [July 2, 2024, 11:31am UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/6 "2024-07-02T11:31:01Z")

</div>

You are right! I know I had issues but I just set up a vanilla Django project and it works. Sorry for the false input!

---

<div class="post-metadata">

**Author:** ![nessita](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/nessita/32/12194_2.png) [@nessita](https://forum.djangoproject.com/u/nessita)\
**Post date:** [September 2, 2024, 5:28pm UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/7 "2024-09-02T17:28:47Z")

</div>

Hello @robhudson, thank you for starting this thread! I’m not (yet?) all familiar with CSP but I know that “Bring CORS and CSP into core” was proposed (but not progressed) both for Google Summer Of Code [2023](https://code.djangoproject.com/wiki/SummerOfCode2023#Security:BringCORSandCSPintocore) and [2024](https://code.djangoproject.com/wiki/SummerOfCode2024#Security:BringCORSandCSPintocore) editions.

With that in mind, and because we would need some guidance of the Steering Council regarding a few potentially contentious topics such as adding a couple of new settings, I think we should summon [@steering\_council](https://forum.djangoproject.com/groups/steering_council) (which coincidentally includes Adam and James who were listed as potential mentors for this GSoC project in 2023) for them to provide some guidance on the next steps.

As far as my understanding of DEP goes, this wouldn’t require one since we have the accepted ticket, but it would be benficial if you could, Rob, to clearly list the items that may need resolution and the options for each one in order to ease the decision making process.

Also for the rest of the readers, the draft proposal mentioned by Rob is [Fixed #15727 -- Added Content Security Policy (CSP) support. by robhudson · Pull Request #18215 · django/django · GitHub](https://github.com/django/django/pull/18215)

---

<div class="post-metadata">

**Author:** ![ubernostrum](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/ubernostrum/32/54_2.png) [@ubernostrum](https://forum.djangoproject.com/u/ubernostrum)\
**Post date:** [September 3, 2024, 12:51am UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/8 "2024-09-03T00:51:54Z")

</div>

I don’t think adding CSP support is large enough to require a DEP. If it were going to be a larger overhaul of the security middleware, maybe, but I think CSP can be added without one, and probably CORS can be added too without one.

One thing that’d be really nice to get out of this, but is _not_ a hard requirement, would be to consolidate the configuration into a top-level `SECURITY` or `SECURITY_MIDDLEWARE` setting as noted in that linked thread – right now the config for all the things `SecurityMiddleware` does is a bit complicated and fragmented.

---

<div class="post-metadata">

**Author:** ![ubernostrum](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/ubernostrum/32/54_2.png) [@ubernostrum](https://forum.djangoproject.com/u/ubernostrum)\
**Post date:** [September 3, 2024, 12:54am UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/9 "2024-09-03T00:54:21Z")

</div>

Like, maybe the way this gets done is

1. Add support to `SecurityMiddleware` for reading from a `SECURITY` dict in settings, falling back to the old individual settings when `SECURITY` is not present, deprecate the old individual settings.
2. To encourage people to migrate to it, CSP is introduced as a feature _only_ supported via the `SECURITY` dict
3. Same approach for CORS

---

<div class="post-metadata">

**Author:** ![benjaoming](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/benjaoming/32/11815_2.png) [@benjaoming](https://forum.djangoproject.com/u/benjaoming)\
**Post date:** [September 10, 2024, 9:51am UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/10 "2024-09-10T09:51:11Z")

</div>

It would be nice with a discussion around the default behavior and what conventions to establish through documentation examples / `django startproject` (or pardons if I missed that, the historic track is really long). Another example of default behavior is for `DEBUG=True`, should we then switch off CSP (same as ALLOWED\_HOSTS)? Or does it somehow magically add localhost-like addresses? Maybe django-csp has some experience to reuse!

Even if we do add CSP, do we just allow all contents and hosts `*` ? Do we switch on reporting etc? How much should the new tutorial user be bothered?

It’s also important to ask how this security layer should be documented - should we want to put emphasis on some preference for having it in the HTTP server? To me, it’s not obvious that Django should be adding these headers if the developer has access to her HTTP server’s configuration.

Maybe a way forward could be to 1) introduce opt-in CSP support in core and 2) start the discussion around default behavior for a subsequent release?

> I don’t think adding CSP support is large enough to require a DEP.

> **Side-track about the role of DEPs**
>
> It should not be the size of the implementation that warrants a DEP. I’m sure that a well-written DEP for a change that can be perceived as small is also welcome, if it helps to guide the subsequent implementation in the right direction. In this case, we’ve seen multiple efforts go down the drain, and I would speculate that a DEP could have helped! Rather than code footprint, it’s more a question of decisions/vetting/approval/complexity/communication. If someone wanted to go the DEP-way with this, I think that could work really well, too 👍 Your proposal for a single `SECURITY` setting also sounds like DEP material, if it was to happen 🙂 (I can think of a number of reasons why this simple proposal is also complex at the same time).

---

<div class="post-metadata">

**Author:** ![robhudson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/robhudson/32/18764_2.png) [@robhudson](https://forum.djangoproject.com/u/robhudson)\
**Post date:** [September 26, 2024, 7:54pm UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/11 "2024-09-26T19:54:19Z")

</div>

I reached out to @adamchainz while here at DjangoCon and it was suggested that CSP be in its own middleware, like CSRF or click-jacking, as adding CSP to `SecurityMiddleware` would bloat things. I’m adjusting my branch at the djangocon sprints to follow this recommendation.

I did consider the changes to the various settings that affect the `SecurityMiddleware`, and I do agree, organizing them under a `SECURITY` dict would be nice. I did start on a patch but then felt like I was hading off on a tangent so I paused work there. If that’s something that’s desired I’d be happy to help out after CSP work, but would like to stay focused on that for the moment.

---

<div class="post-metadata">

**Author:** ![robhudson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/robhudson/32/18764_2.png) [@robhudson](https://forum.djangoproject.com/u/robhudson)\
**Post date:** [October 7, 2024, 10:27pm UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/12 "2024-10-07T22:27:10Z")

</div>

Hi @benjaoming!

You raise a lot of important points and considerations.

In my view, Django should include opt-in support for CSP. However, I don’t believe Django should provide a default CSP configuration. Each project has unique requirements and will need to tailor a CSP to fit its specific needs. It’s also up to the project’s developers to decide whether to apply the CSP in report-only mode or enforced mode, depending on the nature and security needs of their project.

The django-csp project does disable CSP when `DEBUG=True` and for 404s or 500 errors to ensure Django’s debug view runs without issues. Aside from that, enabling CSP is useful for local development and believe django-csp’s approach is also a good fit for Django.

---

<div class="post-metadata">

**Author:** ![benjaoming](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/benjaoming/32/11815_2.png) [@benjaoming](https://forum.djangoproject.com/u/benjaoming)\
**Post date:** [October 8, 2024, 11:01am UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/13 "2024-10-08T11:01:46Z")

</div>

@robhudson I’d love to chip in on the documentation-side of things, once people agree on the various concerns and considerations that should be put into effect. I started a PR already which I think can precede this effort. Like a little step-stone. What do you think? [Docs: Add CSP to Security topic by benjaoming · Pull Request #18212 · django/django · GitHub](https://github.com/django/django/pull/18212)

---

<div class="post-metadata">

**Author:** ![robhudson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/robhudson/32/18764_2.png) [@robhudson](https://forum.djangoproject.com/u/robhudson)\
**Post date:** [October 9, 2024, 3:03pm UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/14 "2024-10-09T15:03:28Z")

</div>

Documentation help would be amazing. It was requested to make CSP docs their own similar to CSRF. My plan was to wait until all the code was in place before working on documentation but I do have piece here and there, not checked-in, that I was getting a start on.

---

<div class="post-metadata">

**Author:** ![nessita](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/nessita/32/12194_2.png) [@nessita](https://forum.djangoproject.com/u/nessita)\
**Post date:** [July 17, 2025, 5:17pm UTC](https://forum.djangoproject.com/t/adding-csp-support-to-django/31526/15 "2025-07-17T17:17:09Z")

</div>

Perhaps relevant for further consideration: [CSP and GeoDjango](https://forum.djangoproject.com/t/csp-and-geodjango/41879)
